Bekerja dengan AppBar

Panel aplikasi atas memberikan tempat yang konsisten di sepanjang bagian atas jendela aplikasi untuk menampilkan informasi dan tindakan dari layar saat ini.

contoh panel aplikasi atas
Gambar 1. Contoh panel aplikasi atas.

Saat menggunakan fragmen, panel aplikasi dapat diterapkan sebagai ActionBar yang dimiliki oleh aktivitas host atau toolbar dalam tata letak fragmen. Kepemilikan panel aplikasi bervariasi, tergantung pada kebutuhan aplikasi Anda.

Jika semua layar Anda menggunakan panel aplikasi yang sama yang selalu ada di bagian atas dan membentang lebar layar, sebaiknya gunakan panel tindakan yang disediakan tema yang dihosting oleh aktivitas. Menggunakan panel aplikasi tema membantu mempertahankan tampilan yang konsisten dan menyediakan tempat untuk menghosting menu opsi dan tombol atas.

Gunakan toolbar yang dihosting oleh fragmen jika Anda ingin dapat lebih mengontrol ukuran, penempatan, dan animasi panel aplikasi di beberapa layar. Misalnya, Anda mungkin perlu menciutkan panel aplikasi atau panel yang membentang hanya setengah lebar layar dan berada di tengah secara vertikal.

Memahami berbagai pendekatan dan menerapkan pendekatan yang tepat akan menghemat waktu dan membantu memastikan aplikasi Anda berfungsi dengan baik. Situasi yang berbeda memerlukan pendekatan yang berbeda untuk hal-hal seperti meng-inflate menu dan merespons interaksi pengguna.

Contoh dalam topik ini mereferensikan ExampleFragment yang berisi profil yang dapat diedit. Fragmen ini meng-inflate menu yang ditentukan XML berikut dalam panel aplikasinya:

<!-- sample_menu.xml -->
<menu
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/action_settings"
        android:icon="@drawable/ic_settings"
        android:title="@string/settings"
        app:showAsAction="ifRoom"/>
    <item
        android:id="@+id/action_done"
        android:icon="@drawable/ic_done"
        android:title="@string/done"
        app:showAsAction="ifRoom|withText"/>

</menu>

Menu berisi dua opsi: satu untuk bernavigasi ke layar profil, dan satu untuk menyimpan perubahan profil yang dilakukan.

Panel aplikasi yang dimiliki aktivitas

Panel aplikasi paling sering dimiliki oleh aktivitas host. Bila panel aplikasi dimiliki oleh aktivitas, fragmen dapat berinteraksi dengan panel aplikasi dengan mengganti metode framework yang dipanggil selama pembuatan fragmen.

Mendaftar dengan aktivitas

Anda harus memberi tahu sistem bahwa fragmen panel aplikasi Anda berpartisipasi dalam populasi menu opsi. Untuk melakukannya, panggil setHasOptionsMenu(true) dalam metode onCreate(Bundle) fragmen Anda, seperti yang ditunjukkan pada contoh berikut:

Kotlin

class ExampleFragment : Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }
}

Java

public class ExampleFragment extends Fragment {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }
}

setHasOptionsMenu(true) memberi tahu sistem bahwa fragmen Anda ingin menerima callback terkait menu. Saat peristiwa terkait menu terjadi (pembuatan, klik, dan sebagainya), metode penanganan peristiwa akan dipanggil di aktivitas terlebih dahulu sebelum dipanggil di fragmen. Perlu diperhatikan bahwa logika aplikasi Anda tidak boleh tergantung pada urutan ini. Jika beberapa fragmen dihosting oleh aktivitas yang sama, setiap fragmen dapat menyediakan opsi menu. Dalam hal ini, urutan callback tergantung pada urutan penambahan fragmen.

Meng-inflate menu

Untuk menggabungkan menu ke menu opsi panel aplikasi, ganti onCreateOptionsMenu() dalam fragmen Anda. Metode ini menerima menu panel aplikasi saat ini dan MenuInflater sebagai parameter. Gunakan inflater menu untuk membuat instance menu fragmen, lalu gabungkan ke menu saat ini, seperti yang ditunjukkan pada contoh berikut:

Kotlin

class ExampleFragment : Fragment() {
    ...

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        inflater.inflate(R.menu.sample_menu, menu)
    }
}

Java

public class ExampleFragment extends Fragment {
    ...

    @Override
    public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
       inflater.inflate(R.menu.sample_menu, menu);
    }
}

Gambar 2 menunjukkan menu yang diperbarui.

menu opsi sekarang berisi fragmen menu Anda
Gambar 2. Menu opsi sekarang berisi fragmen menu Anda.

Menangani peristiwa klik

Setiap aktivitas dan fragmen yang berpartisipasi dalam menu opsi dapat merespons sentuhan. onOptionsItemSelected() fragmen menerima item menu yang dipilih sebagai parameter dan menampilkan boolean untuk menunjukkan apakah sentuhan telah digunakan atau belum. Setelah aktivitas atau fragmen menampilkan true dari onOptionsItemSelected(), tidak ada fragmen lain yang berpartisipasi yang akan menerima callback.

Dalam implementasi onOptionsItemSelected(), gunakan pernyataan switch pada itemId dari item menu. Jika item yang dipilih adalah milik Anda, tangani sentuhan dengan sesuai dan tampilkan true untuk menunjukkan bahwa peristiwa klik telah ditangani. Jika item yang dipilih bukan milik Anda, panggil implementasi super. Secara default, implementasi super menampilkan false untuk mengizinkan pemrosesan menu untuk dilanjutkan.

Kotlin

class ExampleFragment : Fragment() {
    ...

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            R.id.action_settings -> {
                // navigate to settings screen
                true
            }
            R.id.action_done -> {
                // save profile changes
                true
            }
            else -> super.onOptionsItemSelected(item)
        }
    }
}

Java

public class ExampleFragment extends Fragment {
    ...

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_settings:  {
                // navigate to settings screen
                return true;
            }
            case R.id.action_done: {
                // save profile changes
                return true;
            }
            default:
                return super.onOptionsItemSelected(item);
        }

    }

}

Mengubah menu secara dinamis

Logika untuk menyembunyikan atau menampilkan tombol atau mengubah ikon harus ditempatkan di onPrepareOptionsMenu(). Metode ini dipanggil tepat sebelum setiap instance yang menampilkan menu.

Melanjutkan dengan contoh sebelumnya, tombol Simpan tidak akan terlihat hingga pengguna mulai mengedit, dan tombol akan menghilang setelah pengguna menyimpan. Menambahkan logika ini ke onPrepareOptionsMenu() akan memastikan menu selalu ditampilkan dengan benar:

Kotlin

class ExampleFragment : Fragment() {
    ...

    override fun onPrepareOptionsMenu(menu: Menu){
        super.onPrepareOptionsMenu(menu)
        val item = menu.findItem(R.id.action_done)
        item.isVisible = isEditing
    }
}

Java

public class ExampleFragment extends Fragment {
    ...

    @Override
    public void onPrepareOptionsMenu(@NonNull Menu menu) {
        super.onPrepareOptionsMenu(menu);
        MenuItem item = menu.findItem(R.id.action_done);
        item.setVisible(isEditing);
    }
}

Bila Anda perlu memperbarui menu, misalnya, saat pengguna menekan tombol Edit untuk mengedit info profil, Anda harus memanggil invalidateOptionsMenu() pada aktivitas host untuk meminta sistem memanggil onCreateOptionsMenu(). Setelah pembatalan validasi, Anda dapat melakukan pembaruan di onCreateOptionsMenu(). Setelah menu di-inflate, sistem akan memanggil onPrepareOptionsMenu() dan memperbarui menu untuk mencerminkan status fragmen saat ini.

Kotlin

class ExampleFragment : Fragment() {
    ...

    fun updateOptionsMenu() {
        isEditing = !isEditing
        requireActivity().invalidateOptionsMenu()
    }
}

Java

public class ExampleFragment extends Fragment {
    ...

    public void updateOptionsMenu() {
        isEditing = !isEditing;
        requireActivity().invalidateOptionsMenu();
    }
}

Panel aplikasi yang dimiliki fragmen

Jika sebagian besar layar di aplikasi tidak memerlukan panel aplikasi, atau jika salah satu layar memerlukan panel aplikasi yang sangat berbeda, Anda dapat menambahkan Toolbar ke tata letak fragmen. Meskipun Anda dapat menambahkan Toolbar di mana saja dalam hierarki tampilan fragmen, biasanya Anda harus menyimpannya di bagian atas layar. Untuk menggunakan Toolbar di fragmen Anda, sediakan ID dan dapatkan referensi ke ID tersebut dalam fragmen Anda, seperti yang Anda lakukan dengan tampilan lainnya.

<androidx.appcompat.widget.Toolbar
    android:id="@+id/myToolbar"
    ... />

Saat menggunakan panel aplikasi yang dimiliki fragmen, sebaiknya Anda menggunakan Toolbar API secara langsung. Jangan gunakan API menu setSupportActionBar() dan Fragment, yang hanya sesuai untuk panel aplikasi yang dimiliki aktivitas.

Meng-inflate menu

Metode praktis Toolbar inflateMenu(int) menggunakan ID resource menu sebagai parameter. Untuk meng-inflate resource menu XML ke toolbar, teruskan resId ke metode ini, seperti yang ditunjukkan pada contoh berikut:

Kotlin

class ExampleFragment : Fragment() {
    ...

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        ...

        viewBinding.myToolbar.inflateMenu(R.menu.sample_menu)
    }
}

Java

public class ExampleFragment extends Fragment {
    ...

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        ...

        viewBinding.myToolbar.inflateMenu(R.menu.sample_menu);
    }

}

Untuk meng-inflate resource menu XML yang lain, panggil metode ini lagi dengan resId dari menu baru. Item menu baru ditambahkan ke menu, dan item menu yang ada tidak akan diubah atau dihapus.

Jika Anda ingin mengganti kumpulan menu yang ada, hapus menu sebelum memanggil inflateMenu(int) dengan ID menu baru.

Kotlin

class ExampleFragment : Fragment() {
    ...

    fun clearToolbarMenu() {
        viewBinding.myToolbar.menu.clear()
    }
}

Java

public class ExampleFragment extends Fragment {

    ...
    public void clearToolbarMenu() {

        viewBinding.myToolbar.getMenu().clear()

    }

}

Menangani peristiwa klik

Anda dapat meneruskan OnMenuItemClickListener langsung ke toolbar menggunakan metode setOnMenuItemClickListener(). Pemroses ini dipanggil setiap kali pengguna memilih item menu dari tombol tindakan yang ditampilkan di akhir toolbar atau tambahan terkait. MenuItem yang dipilih diteruskan ke metode onMenuItemClick() pemroses dan dapat digunakan untuk memakai tindakan, seperti yang ditunjukkan dalam contoh berikut:

Kotlin

class ExampleFragment : Fragment() {
    ...

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        ...

        viewBinding.myToolbar.setOnMenuItemClickListener {
            when (it.itemId) {
                R.id.action_settings -> {
                    // Navigate to settings screen
                    true
                }
                R.id.action_done -> {
                    // Save profile changes
                    true
                }
                else -> false
            }
        }
    }
}

Java

public class ExampleFragment extends Fragment {
    ...

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        ...

        viewBinding.myToolbar.setOnMenuItemClickListener(item -> {
            switch (item.getItemId()) {
                case R.id.action_settings:
                    // Navigate to settings screen
                    return true;
                case R.id.action_done:
                    // Save profile changes
                    return true;
                default:
                    return false;
            }
        });
    }
}

Mengubah menu secara dinamis

Bila fragmen memiliki panel aplikasi, Anda dapat mengubah Toolbar pada runtime seperti halnya tampilan lain.

Melanjutkan dengan contoh sebelumnya, opsi menu Simpan tidak akan terlihat hingga pengguna mulai mengedit, dan akan menghilang lagi saat ditekan:

Kotlin

class ExampleFragment : Fragment() {
    ...

    fun updateToolbar() {
        isEditing = !isEditing

        val saveItem = viewBinding.myToolbar.menu.findItem(R.id.action_done)
        saveItem.isVisible = isEditing

    }
}

Java

public class ExampleFragment extends Fragment {
    ...

    public void updateToolbar() {
        isEditing = !isEditing;

        MenuItem saveItem = viewBinding.myToolbar.getMenu().findItem(R.id.action_done);
        saveItem.setVisible(isEditing);
    }

}

Jika ada, tombol navigasi akan muncul saat toolbar dimulai. Menyetel ikon navigasi pada toolbar akan membuatnya terlihat. Anda juga dapat menetapkan onClickListener() khusus navigasi yang dipanggil setiap kali pengguna mengklik tombol navigasi, seperti ditunjukkan dalam contoh berikut:

Kotlin

class ExampleFragment : Fragment() {
    ...

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        ...

        myToolbar.setNavigationIcon(R.drawable.ic_back)

        myToolbar.setNavigationOnClickListener { view ->
            // Navigate somewhere
        }
    }
}

Java

public class ExampleFragment extends Fragment {
    ...

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        ...

        viewBinding.myToolbar.setNavigationIcon(R.drawable.ic_back);
        viewBinding.myToolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Navigate somewhere
            }
        });
    }
}