Bekerja dengan AppBar

Panel aplikasi atas menyediakan 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.

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

Jika semua layar Anda menggunakan panel aplikasi yang sama yang selalu ada di bagian atas dan membentang lebar layar, gunakan panel tindakan yang disediakan tema yang dihosting oleh aktivitas. Menggunakan panel aplikasi tema akan 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.

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

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, seperti klik, metode penanganan peristiwa akan dipanggil di aktivitas terlebih dahulu sebelum dipanggil di fragmen.

Namun, jangan mengandalkan urutan ini dalam logika aplikasi Anda. Jika aktivitas yang sama menghosting beberapa fragmen, setiap fragmen dapat menyediakan opsi menu, dalam hal ini urutan callback bergantung 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 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

Tempatkan logika untuk menyembunyikan atau menampilkan tombol atau mengubah ikon di onPrepareOptionsMenu(). Metode ini dipanggil tepat sebelum menu ditampilkan.

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 membuat menu 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);
    }
}

Jika Anda perlu memperbarui menu, seperti ketika pengguna menekan tombol Edit untuk mengedit info profil, panggil invalidateOptionsMenu() pada aktivitas host untuk meminta sistem memanggil onCreateOptionsMenu(). Setelah pembatalan validasi, Anda dapat melakukan pembaruan di onCreateOptionsMenu(). Setelah menu meng-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 Anda tidak memerlukan panel aplikasi, atau jika satu layar memerlukan panel aplikasi yang berbeda dari yang lain, Anda dapat menambahkan Toolbar ke tata letak fragmen. Meskipun Anda dapat menambahkan Toolbar di mana saja dalam hierarki tampilan fragmen, biasanya Anda 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. Anda juga dapat mempertimbangkan untuk menganimasikan toolbar menggunakan perilaku CoordinatorLayout.

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

Saat menggunakan panel aplikasi yang dimiliki fragmen, Google merekomendasikan untuk 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, seperti yang ditunjukkan pada contoh berikut:

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 saat pengguna memilih item menu dari tombol tindakan yang ditampilkan di akhir toolbar atau overflow 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

Jika fragmen memiliki panel aplikasi, Anda dapat memodifikasi Toolbar saat runtime seperti halnya tampilan lain.

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

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.
            }
        });
    }
}