Register now for Android Dev Summit 2019!

Membuat UI yang fleksibel

Saat mendesain aplikasi agar mendukung berbagai ukuran layar, Anda bisa menggunakan kembali fragmen dalam konfigurasi tata letak lainnya untuk mengoptimalkan pengalaman pengguna berdasarkan ruang layar yang tersedia.

Misalnya, pada perangkat handset, menampilkan satu fragmen dalam satu waktu mungkin sesuai untuk antarmuka pengguna satu panel. Sebaliknya, Anda mungkin perlu menyetel fragmen secara berdampingan di tablet dengan ukuran layar yang lebih lebar untuk menampilkan lebih banyak informasi kepada pengguna.

Gambar 1. Dua fragmen, ditampilkan dalam konfigurasi yang berbeda untuk aktivitas yang sama pada ukuran layar yang berbeda. Di layar berukuran besar, kedua fragmen pas secara berdampingan, tetapi pada perangkat handset, hanya satu fragmen yang pas dalam satu waktu sehingga harus menggantikan satu sama lain ketika pengguna melakukan navigasi.

Class FragmentManager menyediakan metode yang memungkinkan Anda menambahkan, menghapus, dan mengganti fragmen ke suatu aktivitas pada waktu proses untuk menciptakan pengalaman dinamis.

Untuk informasi selengkapnya tentang menerapkan Fragmen, lihat resource berikut.

Menambahkan Fragmen ke Aktivitas pada Waktu Proses

Daripada menentukan fragmen untuk suatu aktivitas dalam file tata letak, seperti dalam tutorial sebelumnya dengan elemen <fragment>, Anda bisa menambahkan fragmen ke aktivitas pada waktu proses aktivitas. Hal ini diperlukan jika Anda berencana mengubah fragmen ketika aktivitas masih digunakan.

Untuk melakukan transaksi seperti menambahkan atau menghapus fragmen, Anda harus menggunakan FragmentManager untuk membuat FragmentTransaction, yang menyediakan API untuk menambahkan, menghapus, mengganti, dan melakukan transaksi fragmen lainnya.

Jika aktivitas mengizinkan fragmen untuk dihapus dan diganti, Anda harus menambahkan fragmen awal ke aktivitas pada saat metode onCreate() aktivitas berjalan.

Salah satu aturan penting saat menangani fragmen, khususnya saat menambahkan fragmen pada waktu proses adalah bahwa tata letak aktivitas harus menyertakan penampung View sebagai tempat menyisipkan fragmen.

Tata letak berikut ini merupakan alternatif tata letak dalam tutorial sebelumnya yang hanya menampilkan satu fragmen pada satu waktu. Untuk mengganti satu fragmen dengan yang lain, tata letak aktivitas menyertakan FrameLayout kosong yang bertindak sebagai penampung fragmen.

Perhatikan bahwa nama filenya sama dengan file tata letak dalam tutorial sebelumnya, tetapi direktori tata letaknya tidak memiliki qualifier large sehingga tata letak ini digunakan ketika layar perangkat lebih kecil dari large karena layar tidak pas dengan kedua fragmen di waktu yang bersamaan.

res/layout/news_articles.xml:

    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    

Dalam aktivitas Anda, panggil getSupportFragmentManager() untuk mendapatkan FragmentManager menggunakan Support Library API. Kemudian, panggil beginTransaction() untuk membuat FragmentTransaction dan panggil add() untuk menambahkan fragmen.

Anda bisa melakukan beberapa transaksi fragmen untuk aktivitas menggunakan FragmentTransaction yang sama. Jika sudah siap untuk melakukan perubahan, Anda harus memanggil commit().

Contohnya, berikut adalah cara menambahkan fragmen ke tata letak sebelumnya:

Kotlin

    import android.os.Bundle
    import android.support.v4.app.FragmentActivity

    class MainActivity : FragmentActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.news_articles)

            // Check that the activity is using the layout version with
            // the fragment_container FrameLayout
            if (findViewById(R.id.fragment_container) != null) {

                // However, if we're being restored from a previous state,
                // then we don't need to do anything and should return or else
                // we could end up with overlapping fragments.
                if (savedInstanceState != null) {
                    return;
                }

                // Create a new Fragment to be placed in the activity layout
                val firstFragment = HeadlinesFragment()

                // In case this activity was started with special instructions from an
                // Intent, pass the Intent's extras to the fragment as arguments
                firstFragment.arguments = intent.extras

                // Add the fragment to the 'fragment_container' FrameLayout
                supportFragmentManager.beginTransaction()
                        .add(R.id.fragment_container, firstFragment).commit()
            }
        }
    }
    

Java

    import android.os.Bundle;
    import android.support.v4.app.FragmentActivity;

    public class MainActivity extends FragmentActivity {
        @Override
        public void onCreate(Bundle savedInstanceState?) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.news_articles);

            // Check that the activity is using the layout version with
            // the fragment_container FrameLayout
            if (findViewById(R.id.fragment_container) != null) {

                // However, if we're being restored from a previous state,
                // then we don't need to do anything and should return or else
                // we could end up with overlapping fragments.
                if (savedInstanceState != null) {
                    return;
                }

                // Create a new Fragment to be placed in the activity layout
                HeadlinesFragment firstFragment = new HeadlinesFragment();

                // In case this activity was started with special instructions from an
                // Intent, pass the Intent's extras to the fragment as arguments
                firstFragment.setArguments(getIntent().getExtras());

                // Add the fragment to the 'fragment_container' FrameLayout
                getSupportFragmentManager().beginTransaction()
                        .add(R.id.fragment_container, firstFragment).commit();
            }
        }
    }
    

Karena fragmen telah ditambahkan ke penampung FrameLayout pada waktu proses, bukan menentukannya dalam tata letak aktivitas dengan elemen <fragment>, aktivitas bisa menghapus fragmen dan menggantinya dengan yang lain.

Mengganti Satu Fragmen dengan Fragmen Lain

Prosedur untuk mengganti fragmen mirip dengan menambahkannya, tetapi memerlukan metode replace(), bukan add().

Perlu diingat bahwa saat Anda melakukan transaksi fragmen, seperti mengganti atau menghapusnya, mengizinkan pengguna untuk menavigasi mundur dan "mengurungkan" perubahan sering kali merupakan tindakan yang tepat. Untuk memungkinkan pengguna menavigasi mundur dalam transaksi fragmen, Anda harus memanggil addToBackStack() sebelum menjalankan FragmentTransaction.

Catatan: Ketika Anda menghapus atau mengganti fragmen dan menambahkan transaksi ke back stack, fragmen yang dihapus akan dihentikan (bukan dimusnahkan). Jika pengguna menavigasi mundur untuk memulihkannya, fragmen akan dimulai ulang. Jika Anda tidak menambahkan transaksi ke back stack, fragmen akan dimusnahkan saat dihapus atau diganti.

Contoh mengganti satu fragmen dengan lainnya:

Kotlin

    // Create fragment and give it an argument specifying the article it should show
    val newFragment = ArticleFragment()
    Bundle args = Bundle()
    args.putInt(ArticleFragment.ARG_POSITION, position)
    newFragment.arguments = args

    val transaction = supportFragmentManager.beginTransaction().apply {
      // Replace whatever is in the fragment_container view with this fragment,
      // and add the transaction to the back stack so the user can navigate back
      replace(R.id.fragment_container, newFragment)
      addToBackStack(null)
    }

    // Commit the transaction
    transaction.commit();
    

Java

    // Create fragment and give it an argument specifying the article it should show
    ArticleFragment newFragment = new ArticleFragment();
    Bundle args = new Bundle();
    args.putInt(ArticleFragment.ARG_POSITION, position);
    newFragment.setArguments(args);

    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

    // Replace whatever is in the fragment_container view with this fragment,
    // and add the transaction to the back stack so the user can navigate back
    transaction.replace(R.id.fragment_container, newFragment);
    transaction.addToBackStack(null);

    // Commit the transaction
    transaction.commit();
    

Metode addToBackStack() mengambil parameter string opsional yang menentukan nama unik untuk transaksi. Nama ini tidak diperlukan kecuali Anda berencana melakukan operasi fragmen lanjutan menggunakan FragmentManager..BackStackEntry API.