Tata Letak Adaptif

1. Sebelum memulai

Perangkat Android hadir dalam berbagai bentuk, ukuran, dan faktor bentuk. Anda harus mendesain aplikasi agar berjalan di berbagai jenis perangkat, mulai dari perangkat layar kecil hingga perangkat layar besar. Developer yang menulis aplikasi yang siap digunakan untuk produksi dapat mendukung Android Wear, Android Auto, dan Android TV, tetapi topik tersebut berada di luar cakupan kursus ini. Jika aplikasi Anda mendukung beragam jenis layar, Anda dapat menyediakannya untuk sejumlah besar pengguna dengan berbagai perangkat.

Aplikasi Anda harus memiliki tata letak yang fleksibel. Daripada menentukan tata letak dengan dimensi mutlak yang memiliki rasio lebar tinggi dan ukuran layar tertentu, tata letak Anda harus mampu menyesuaikan berbagai ukuran dan orientasi layar tanpa masalah. Prinsip yang sama berlaku saat aplikasi berjalan di perangkat foldable, dengan ukuran layar dan rasio lebar tinggi yang dapat berubah saat aplikasi sedang berjalan. Di akhir codelab ini, Anda akan mempelajari pengantar singkat tentang perangkat foldable.

aecb59fc49fb4abf.png

Prasyarat

  • Cara mendownload kode ke Android Studio dan menjalankannya.
  • Pemahaman tentang komponen arsitektur Android ViewModel, dan LiveData.
  • Pengetahuan dasar tentang komponen Navigasi.

Yang akan Anda pelajari

  • Cara menambahkan SlidingPaneLayout ke aplikasi Anda.

Yang akan Anda build

  • Update aplikasi Olahraga agar dapat beradaptasi dengan perangkat layar besar.

Yang akan Anda butuhkan

  • Komputer yang dilengkapi Android Studio.
  • Kode awal untuk aplikasi Olahraga.

Mendownload kode awal untuk codelab ini

Codelab ini menyediakan kode awal bagi Anda untuk diperluas dengan fitur yang dipelajari dalam codelab ini. Kode awal dapat berisi kode yang tidak asing bagi Anda dari codelab sebelumnya dan juga kode yang tidak Anda ketahui yang akan Anda pelajari di codelab berikutnya.

Untuk mendapatkan kode yang dipakai pada codelab ini dari GitHub serta membukanya di Android Studio, lakukan hal berikut.

  1. Mulai Android Studio.
  2. Di jendela Welcome to Android Studio, klik Check out project from Version Control.
  3. Pilih Git.

b89a22e2d8cf3b4e.png

  1. Pada dialog Clone Repository, tempelkan URL kode yang disediakan ke kotak URL.
  2. Klik tombol Test, tunggu, dan pastikan ada pop-up balon berwarna hijau yang bertuliskan Connection successful.
  3. Jika ingin, Anda dapat mengubah Directory menjadi sesuatu yang berbeda dengan default yang disarankan.

e4fb01c402e47bb3.png

  1. Klik Clone. Android Studio mulai mengambil kode Anda.
  2. Di pop-up Checkout from Version Control, klik Yes.

1902d34f29119530.png

  1. Tunggu Android Studio terbuka.
  2. Pilih modul yang tepat untuk codelab pemicu atau kode solusi Anda.

2371589274bce21c.png

  1. Klik tombol Run 11c34fc5e516fb1c.png untuk membuat dan menjalankan kode.

2. Ringkasan aplikasi awal

Aplikasi Olahraga terdiri dari dua layar. Layar pertama menampilkan daftar olahraga. Pengguna dapat memilih item olahraga tertentu dan layar kedua akan ditampilkan. Layar kedua adalah layar detail yang menampilkan berita olahraga yang dipilih. Layar detail menampilkan teks placeholder untuk menyederhanakan implementasi.

Panduan kode awal

Kode awal yang Anda download memiliki tata letak layar daftar dan layar detail yang telah dirancang sebelumnya untuk Anda. Di jalur ini, Anda hanya akan berfokus untuk membuat aplikasi beradaptasi dengan perangkat layar besar. Anda akan menggunakan SlidingPaneLayou untuk memanfaatkan layar besar. Berikut adalah panduan singkat beberapa file untuk membantu Anda memulai.

fragment_sports_list.xml

  • Buka res/layout/fragment_sports_list.xml dalam tampilan Design.
  • File ini berisi tata letak layar pertama di aplikasi Anda yang merupakan daftar olahraga.
  • Tata letak ini terdiri dari Recyclerview yang menampilkan daftar berita olahraga.

19347945e512f94f.png

d9af155f87ddbcdf.png

sports_list_item.xml

  • Buka res/layout/sports_list_item.xml dalam tampilan Design.
  • File ini berisi tata letak setiap item di Recyclerview.
  • Tata letak ini terdiri dari gambar thumbnail olahraga, judul Berita, dan teks placeholder untuk berita olahraga singkat.

afe02fbb229608c2.png

fragment_sports_news.xml

  • Buka res/layout/fragment_sports_news.xml dalam tampilan Design.
  • File ini berisi tata letak layar kedua di aplikasi Anda. Layar ini ditampilkan saat pengguna memilih olahraga dari Recyclerview.
  • Tata letak ini terdiri dari banner gambar olahraga dan teks placeholder untuk berita olahraga.

f21a8edd59a53233.png

main_activity.xml dan content_main.xml

Keduanya menentukan tata letak aktivitas utama dengan satu fragmen.

Grafik navigasi berisi dua tujuan, satu untuk daftar olahraga dan satu lagi untuk berita olahraga.

folder res/values

Anda sudah memahami file resource dalam folder ini.

  • colors.xml berisi warna tema yang digunakan dalam aplikasi.
  • strings.xml berisi semua string yang dibutuhkan aplikasi Anda.
  • themes.xml berisi penyesuaian UI yang dilakukan untuk aplikasi Anda.

MainActivity.kt

File ini berisi kode yang dihasilkan oleh template default untuk menetapkan tampilan konten aktivitas sebagai main_activity.xml. Metode onSupportNavigateUp() diganti untuk menangani navigasi Up default dari panel aplikasi.

model/Sport.kt

File ini adalah class data yang menyimpan data yang akan ditampilkan di setiap baris Recyclerview daftar olahraga.

data/SportsData.kt

File ini berisi fungsi bernama getSportsData() yang menampilkan ArrayList yang sudah terisi otomatis dengan data olahraga hardcode.

SportsViewModel.kt

File ini adalah ViewModel bersama untuk aplikasi. ViewModel dibagikan oleh SportsListFragment, layar pertama yang berisi daftar olahraga, dan oleh NewsDetailsFragment, layar kedua yang berisi berita olahraga terperinci.

  • Properti _currentSport adalah jenis MutableLiveData, yang menyimpan olahraga saat ini yang dipilih oleh pengguna. Properti currentSport adalah properti pendukung untuk _currentSport, dan ditampilkan sebagai versi hanya-baca publik untuk class lain.
  • Properti _sportsData berisi daftar data olahraga. Serupa dengan properti sebelumnya, sportsData adalah versi hanya-baca publik untuk properti ini.
  • Blok init{} penginisialisasi melakukan inisialisasi _currentSport dan _sportsData. _sportsData diinisialisasi dengan seluruh daftar olahraga dari data/SportsData.kt. _currentSport diinisialisasi dengan item pertama dalam daftar.
  • Fungsi updateCurrentSport() menggunakan instance Sports dan mengupdate _currentSport dengan nilai yang diteruskan.

SportsAdapter.kt

File ini adalah adaptor untuk RecyclerView. Di konstruktor, pemroses klik diteruskan. Sebagian besar kode dalam file ini adalah kode boilerplate yang biasa Anda gunakan dari codelab sebelumnya.

SportsListFragment.kt

File ini adalah fragmen layar pertama, tempat daftar olahraga akan ditampilkan.

  • Fungsi onCreateView() meng-inflate XML tata letak fragment_sports_list menggunakan objek binding.
  • Fungsi onViewCreated() menyiapkan adaptor RecyclerView. Fungsi ini memperbarui olahraga yang dipilih oleh pengguna sebagai olahraga saat ini di ViewModel bersama, SportsViewModel. Fungsi ini membuka halaman detail yang berisi berita olahraga dan mengirimkan daftar olahraga ke adaptor untuk ditampilkan menggunakan submitList(List).

NewsDetailsFragment.kt

File ini adalah layar kedua di aplikasi Anda, tempat teks placeholder untuk berita olahraga akan ditampilkan.

  • Fungsi onCreateView() meng-inflate XML tata letak fragment_sports_news menggunakan objek binding.
  • Fungsi onViewCreated() melampirkan observer di properti SportsViewModel, currentSport untuk mengupdate UI secara otomatis saat data berubah. Judul, gambar, dan berita olahraga diperbarui di dalam observer.

Membuat dan menjalankan aplikasi

  1. Buat dan jalankan aplikasi di emulator atau perangkat. Pilih item apa pun dari daftar olahraga, dan aplikasi akan membuka layar kedua yang berisi teks placeholder untuk berita.

3. Pola Daftar-Detail

Aplikasi awal saat ini gagal memanfaatkan ruang layar secara maksimal pada perangkat yang lebih besar seperti tablet. Untuk mengatasi masalah ini, Anda akan menampilkan UI aplikasi menggunakan pola Daftar-Detail, yang akan Anda pelajari di codelab ini.

Menjalankan aplikasi di tablet

Dalam tugas ini, Anda akan membuat emulator dengan profil tablet. Setelah emulator dibuat, Anda akan menjalankan kode awal aplikasi olahraga dan mengamati UI-nya.

  1. Di Android Studio, buka Tools > AVD Manager.
  2. Jendela Android Virtual Device Manager akan ditampilkan. Klik + Create New Virtual Device... yang ditampilkan di bagian bawah.
  3. Jendela Virtual Device Configuration akan ditampilkan. Di sini, Anda akan mengonfigurasi hardware dan OS emulator. Klik Tablet di panel kiri. Pilih Pixel C atau profil hardware serupa lainnya di panel tengah.

5c4600c27a47077e.png

  1. Klik Next.
  2. Pilih image sistem terbaru, pada saat penulisan codelab ini, yang terbaru adalah R (API level 30).
  3. Klik Next.
  4. Anda dapat mengganti nama perangkat virtual sekarang, tindakan ini bersifat opsional.
  5. Klik Finish.
  6. Anda akan diarahkan kembali ke jendela Android Virtual Device Manager. Klik ikon peluncuran 65b3080672a3f31.png di samping perangkat virtual yang baru dibuat.
  7. Emulator dengan profil tablet akan diluncurkan. Harap bersabar, proses ini mungkin memerlukan waktu beberapa saat.
  8. Tutup jendela Android Virtual Device Manager.
  9. Jalankan aplikasi olahraga di emulator yang baru dibuat.

200e209de7a2f0ad.png

Perhatikan, aplikasi tidak menggunakan seluruh layar pada perangkat layar besar. Pola daftar-detail di layar besar lebih efisien daripada pola daftar. Pola item-detail, juga disebut dengan pola master-detail, menampilkan daftar item di satu sisi tata letak dan detailnya ditampilkan di sebelahnya saat Anda mengetuk item. Biasanya, tampilan ini hanya ditampilkan di perangkat layar besar seperti tablet, karena perangkat tersebut memiliki lebih banyak ruang untuk menampilkan konten lainnya.

Gambar berikut adalah contoh pola daftar-detail:

9ebca0de8956275a.png

Pola daftar-detail di atas menampilkan daftar item di sebelah kiri dan detail item yang dipilih di sebelah kanan.

Dengan cara yang sama, jika Anda menggunakan pola di atas dalam aplikasi olahraga, fragmen berita akan menjadi layar detail Anda.

51c9542717d2f875.png

Dalam codelab ini, Anda akan mempelajari cara mengimplementasikan UI daftar-detail menggunakan SlidingPaneLayout.

4. Pola SlidingPaneLayout

UI daftar-detail mungkin perlu berperilaku lain bergantung pada ukuran layar. Pada layar besar, ada cukup ruang untuk menampilkan panel daftar dan panel detail secara berdampingan. Mengklik item daftar akan menampilkan detailnya di panel detail. Namun, konfigurasi ini akan tampak penuh di layar kecil. Daripada menampilkan kedua panel sekaligus, sebaiknya tampilkan panel satu per satu. Awalnya, panel daftar mengisi layar. Mengetuk item akan mengganti panel daftar dengan panel detail untuk item tersebut, yang juga akan mengisi layar.

Anda akan mempelajari cara menggunakan SlidingPaneLayout untuk mengelola logika guna memilih pengalaman pengguna yang sesuai berdasarkan ukuran layar saat ini.

b0a205de3494e95d.gif

Perhatikan bagaimana panel detail bergeser ke atas panel daftar pada layar yang lebih kecil.

Berikut adalah gambar yang mengilustrasikan tampilan SlidingPaneLayout pada layar yang lebih kecil. Amati tampilan panel detail yang tumpang tindih dengan panel daftar saat item dari daftar dipilih. Jadi, kedua panel selalu ada.

1363b67d106ea395.png

c64fa6a0641320dd.png

Oleh karena itu, SlidingPaneLayout dapat menampilkan dua panel secara berdampingan pada perangkat yang lebih besar, dan otomatis beradaptasi untuk menampilkan hanya satu panel pada perangkat yang lebih kecil seperti ponsel.

5. Menambahkan dependensi library

  1. Buka build.gradle (Module: Sports.app).
  2. Di bagian dependencies, sertakan dependensi berikut untuk menggunakan SlidingPaneLayout di aplikasi Anda.
dependencies {
...
    implementation "androidx.slidingpanelayout:slidingpanelayout:1.2.0-beta01"
}

6. Mengonfigurasi XML fragmen daftar olahraga

Dalam tugas ini, Anda akan mengonversi tata letak root fragment_sports_list menjadi SlidingPaneLayout. Seperti yang telah Anda pelajari, SlidingPaneLayout menyediakan tata letak dua panel horizontal untuk penggunaan di bagian atas UI. Tata letak ini menggunakan panel pertama sebagai daftar konten atau browser, di bawah tampilan detail utama guna menampilkan konten di panel lainnya.

Di aplikasi Olahraga, panel pertama adalah RecyclerView yang menampilkan daftar olahraga dan panel kedua menampilkan berita olahraga.

Menambahkan SlidingPaneLayout

  1. Buka fragment_sports_list.xml. Perhatikan bahwa tata letak root adalah FrameLayout.
  2. Ubah FrameLayout menjadi androidx.slidingpanelayout.widget.SlidingPaneLayout.
<androidx.slidingpanelayout.widget.SlidingPaneLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".SportsListFragment">

   <androidx.recyclerview.widget.RecyclerView...>
</androidx.slidingpanelayout.widget.SlidingPaneLayout>
  1. Tambahkan atribut android:id ke SlidingPaneLayout dan beri nilai @+id/sliding_pane_layout.
<androidx.slidingpanelayout.widget.SlidingPaneLayout
   ...
   android:id="@+id/sliding_pane_layout"
   ...>

Menambahkan panel kedua ke SlidingPaneLayout

Dalam tugas ini, Anda akan menambahkan turunan kedua ke SlidingPaneLayout. Turunan ini akan ditampilkan sebagai panel konten kanan.

  1. Di fragment_sports_list.xml, di bawah RecyclerView, tambahkan turunan kedua, androidx.fragment.app.FragmentContainerView.
  2. Tambahkan atribut yang diperlukan, layout_height dan layout_width ke FragmentContainerView. Beri nilai match_parent. Perlu diketahui bahwa Anda akan mengupdate nilai ini nanti.
<androidx.fragment.app.FragmentContainerView
   android:layout_height="match_parent"
   android:layout_width="match_parent"/>
  1. Tambahkan atribut android:id ke FragmentContainerView dan beri nilai @+id/detail_container.
android:id="@+id/detail_container"
  1. Tambahkan NewsDetailsFragment ke FragmentContainerView dengan menggunakan atribut android:name.
android:name="com.example.android.sports.NewsDetailsFragment"

Mengupdate atribut layout_width

SlidingPaneLayout menggunakan lebar dua panel untuk menentukan apakah panel akan ditampilkan secara berdampingan atau tidak. Misalnya, jika panel daftar diukur untuk memiliki ukuran minimum 300dp dan panel detail memerlukan 400dp, SlidingPaneLayout akan otomatis menampilkan dua panel secara berdampingan selama panel memiliki lebar yang tersedia setidaknya 700dp.

Tampilan turunan akan tumpang tindih jika lebar gabungannya melebihi lebar yang tersedia di SlidingPaneLayout. Dalam hal ini, tampilan turunan diperluas untuk mengisi lebar yang tersedia di SlidingPaneLayout.

Untuk menentukan lebar tampilan turunan, Anda harus memiliki beberapa informasi dasar tentang lebar layar perangkat. Tabel berikut menampilkan daftar titik henti sementara tidak berubah untuk Anda guna mendesain, mengembangkan, dan menguji tata letak aplikasi yang dapat diubah ukurannya. Class ini telah dipilih secara khusus untuk menyeimbangkan kesederhanaan tata letak dengan fleksibilitas guna mengoptimalkan aplikasi Anda untuk kasus yang unik.

Lebar

Titik henti sementara

Representasi perangkat

Lebar rapat

< 600dp

99,96% ponsel dalam mode potret

Lebar sedang

600dp+

93,73% tablet dalam mode portrait. Tampilan bagian dalam yang luas dan dibentangkan dalam mode potret

Lebar yang diluaskan

840dp+

97,22% tablet dalam mode lanskap. Tampilan bagian dalam yang luas dan dibentangkan dalam mode lanskap

f9a18939802543dd.png

Di aplikasi Olahraga, Anda ingin menampilkan satu panel, daftar olahraga di ponsel, untuk perangkat dengan lebar kurang dari 600dp. Untuk menampilkan kedua panel pada tablet, lebar gabungan harus lebih besar dari 840dp. Anda dapat menggunakan lebar 550dp untuk turunan pertama, tampilan recycler, dan 300dp untuk turunan kedua, FragmentContainerView.

  1. Di fragment_sports_list.xml, ubah lebar tata letak RecyclerView menjadi 550dp dan lebar FragmentContainerView menjadi 300dp.
<androidx.recyclerview.widget.RecyclerView
   ...
   android:layout_width="550dp"
   .../>

<androidx.fragment.app.FragmentContainerView
   ...
   android:layout_width="300dp"
   .../>
  1. Jalankan aplikasi di emulator dengan profil tablet, dan emulator dengan profil ponsel.

ad148a96d7487e66.png

Perhatikan bahwa dua panel ditampilkan di tablet. Anda akan memperbaiki lebar panel kedua di tablet pada langkah berikutnya.

  1. Jalankan aplikasi di emulator dengan profil ponsel.

a6be6d199d2975ac.png

Menambahkan layout_weight

Dalam tugas ini, Anda akan memperbaiki UI di tablet dan membuat panel kedua menggunakan seluruh ruang yang tersisa.

SlidingPaneLayout mendukung penentuan bagaimana ruang yang tersisa dibagi setelah pengukuran menggunakan parameter tata letak layout_weight pada tampilan turunan jika tampilan tidak tumpang tindih. Parameter ini hanya berlaku untuk lebar.

  1. Di fragment_sports_list.xml, tambahkan layout_weight ke FragmentContainerView dan beri nilai 1. Sekarang, panel kedua akan diperluas untuk mengisi ruang yang tersisa setelah panel daftar diukur.
android:layout_weight="1"
  1. Jalankan aplikasi.

ce3a93fe501ee5dc.png

Selamat! Anda berhasil menambahkan SlidingPaneLayout. Anda belum selesai. Anda harus menerapkan navigasi kembali dan mengupdate panel kedua saat item dipilih dari daftar. Anda akan menerapkannya di tugas selanjutnya.

7. Menukar panel detail

Jalankan aplikasi di emulator dengan profil tablet. Pilih item daftar dari daftar olahraga. Perhatikan bahwa aplikasi membuka panel detail.

8fedee8d4837909.png

Dalam tugas ini, Anda akan memperbaiki masalah ini. Saat ini, konten panel ganda diupdate dengan olahraga yang dipilih, lalu aplikasi akan membuka NewsDetailsFragment.

  1. Pada file SportsListFragment, di fungsi onViewCreated(), temukan baris berikut, yang akan membuka layar detail.
// Navigate to the details screen
val action = SportsListFragmentDirections.actionSportsListFragmentToNewsFragment()
this.findNavController().navigate(action)
  1. Ganti baris di atas dengan kode berikut:
binding.slidingPaneLayout.openPane()

Panggil openPane() di SlidingPaneLayout untuk menukar panel kedua di atas panel pertama. Tindakan ini tidak akan memiliki efek yang terlihat jika kedua panel terlihat seperti di tablet.

  1. Jalankan aplikasi di emulator tablet dan ponsel. Perhatikan bahwa konten panel ganda diupdate dengan benar.

b0d3c8c263be15f8.png

Pada tugas berikutnya, fungsi berikutnya yang akan Anda tambahkan ke aplikasi adalah navigasi kembali kustom.

8. Menambahkan navigasi kembali kustom

Untuk perangkat yang lebih kecil, dengan panel daftar dan detail saling tumpang tindih, Anda harus memastikan bahwa tombol kembali sistem membawa pengguna dari panel detail kembali ke panel daftar. Anda dapat melakukannya dengan memberikan navigasi kembali kustom dan menghubungkan OnBackPressedCallback ke status SlidingPaneLayout saat ini.

Navigasi kembali

Navigasi kembali adalah cara pengguna bergerak mundur dalam histori layar yang sebelumnya mereka kunjungi. Semua perangkat Android menyediakan tombol Kembali untuk jenis navigasi ini. Bergantung pada perangkat Android pengguna, tombol ini mungkin berupa tombol fisik atau tombol software.

Navigasi kembali kustom

Android menyimpan data sebelumnya dari tujuan saat pengguna bernavigasi di dalam aplikasi Anda. Hal ini biasanya memungkinkan Android menavigasi dengan benar ke tujuan sebelumnya saat tombol Kembali ditekan. Namun, ada beberapa kasus ketika aplikasi Anda mungkin perlu mengimplementasikan perilaku Kembali-nya sendiri untuk memberikan pengalaman pengguna sebaik mungkin.

Misalnya, saat menggunakan WebView seperti browser Chrome, Anda mungkin ingin mengganti perilaku tombol Kembali default untuk memungkinkan pengguna kembali menjelajahi histori penjelajahan web mereka, bukan layar sebelumnya di aplikasi Anda.

Demikian pula, Anda harus memberikan navigasi kembali kustom ke SlidingPaneLayout dan menavigasi aplikasi dari panel detail kembali ke panel daftar.

Mengimplementasikan navigasi kembali kustom

Untuk menerapkan navigasi kembali kustom di aplikasi Olahraga, Anda harus:

  • Menentukan callback kustom untuk menangani penekanan tombol kembali, yang menggantikan OnBackPressedCallback.
  • Mendaftarkan dan menambahkan instance callback.

Pertama, tentukan callback kustom.

  1. Dalam file SportsListFragment, tambahkan class baru di bawah definisi class SportsListFragment. Beri nama SportsListOnBackPressedCallback.
  2. Teruskan instance private dari SlidingPaneLayout sebagai parameter konstruktor.
class SportsListOnBackPressedCallback(
   private val slidingPaneLayout: SlidingPaneLayout
)
  1. Perluas class dari OnBackPressedCallback. Class OnBackPressedCallback menangani callback onBackPressed. Anda akan segera memperbaiki error parameter konstruktor.
class SportsListOnBackPressedCallback(
   private val slidingPaneLayout: SlidingPaneLayout
): OnBackPressedCallback()

Konstruktor untuk OnBackPressedCallback mengambil logika boolean untuk status aktif awal. Hanya saat callback diaktifkan (misalnya, isEnabled() menampilkan benar), dispatcher akan memanggil handleOnBackPressed() callback untuk menangani peristiwa tombol Kembali.

  1. Teruskan slidingPaneLayout.isSlideable* && slidingPaneLayout.isOpen* sebagai parameter konstruktor untuk OnBackPressedCallback. Boolean isSlideable hanya akan bernilai benar jika panel kedua dapat digeser, yang akan berada di layar yang lebih kecil dan satu panel yang ditampilkan. Nilai isOpen akan menjadi true jika panel kedua - panel konten sepenuhnya terbuka.
class SportsListOnBackPressedCallback(
   private val slidingPaneLayout: SlidingPaneLayout
): OnBackPressedCallback(slidingPaneLayout.isSlideable && slidingPaneLayout.isOpen)

Kode ini akan memastikan bahwa callback hanya diaktifkan pada perangkat dengan layar yang lebih kecil dan saat panel konten terbuka.

  1. Untuk memperbaiki error terkait metode yang tidak diterapkan, klik bohlam merah cb1d366f3ceb9ad5.png, lalu pilih Implement members.
  2. Klik OK di pop-up Implement members untuk mengganti metode handleOnBackPressed.

Class Anda akan terlihat seperti ini:

class SportsListOnBackPressedCallback(
   private val slidingPaneLayout: SlidingPaneLayout
): OnBackPressedCallback(slidingPaneLayout.isSlideable && slidingPaneLayout.isOpen) {
   /**
    * Callback for handling the [OnBackPressedDispatcher.onBackPressed] event.
    */
   override fun handleOnBackPressed() {
       TODO("Not yet implemented")
   }
}
  1. Di dalam fungsi handleOnBackPressed(), hapus pernyataan TODO dan tambahkan kode berikut untuk menutup panel konten dan kembali ke panel daftar.
slidingPaneLayout.closePane()

Memantau peristiwa SlidingPaneLayout

Selain menangani peristiwa penekanan tombol kembali, Anda harus memproses dan memantau peristiwa yang terkait dengan panel geser. Saat panel konten bergeser, callback harus diaktifkan atau dinonaktifkan sebagaimana mestinya. Anda akan menggunakan PanelSlideListener untuk melakukannya.

Antarmuka SlidingPaneLayout.PanelSlideListener berisi tiga metode abstrak onPanelSlide(), onPanelOpened(), dan onPanelClosed(). Metode ini dipanggil saat panel detail bergeser, terbuka, dan tertutup.

  1. Perluas class SportsListOnBackPressedCallback dari SlidingPaneLayout.PanelSlideListener.
  2. Untuk mengatasi error, terapkan tiga metode. Klik bohlam merah dan pilih Implement members di Android Studio.

bddae0e597f6e1d3.png

  1. Class SportsListOnBackPressedCallback Anda akan terlihat seperti berikut:
class SportsListOnBackPressedCallback(
   private val slidingPaneLayout: SlidingPaneLayout
): OnBackPressedCallback(slidingPaneLayout.isSlideable && slidingPaneLayout.isOpen),
  SlidingPaneLayout.PanelSlideListener{

   override fun handleOnBackPressed() {
       slidingPaneLayout.closePane()
   }

   override fun onPanelSlide(panel: View, slideOffset: Float) {
       TODO("Not yet implemented")
   }

   override fun onPanelOpened(panel: View) {
       TODO("Not yet implemented")
   }

   override fun onPanelClosed(panel: View) {
       TODO("Not yet implemented")
   }
}
  1. Hapus pernyataan TODO.
  2. Aktifkan callback OnBackPressedCallback, saat panel detail dibuka (terlihat) . Hal ini dapat dilakukan dengan melakukan panggilan ke fungsi setEnabled() dan meneruskan true. Tulis kode berikut di dalam onPanelOpened():
setEnabled(true)
  1. Kode di atas dapat disederhanakan menggunakan sintaksis akses properti.
override fun onPanelOpened(panel: View) {
   isEnabled = true
}
  1. Demikian pula, setel isEnabled ke false, saat panel detail ditutup.
override fun onPanelClosed(panel: View) {
   isEnabled = false
}
  1. Langkah terakhir dalam menyelesaikan callback adalah menambahkan class pemroses SportsListOnBackPressedCallback ke daftar pemroses yang akan menerima notifikasi terkait peristiwa geser panel detail. Tambahkan blok init ke class SportsListOnBackPressedCallback. Di dalam blok init, lakukan panggilan ke slidingPaneLayout.addPanelSlideListener() yang meneruskan this.
init {
   slidingPaneLayout.addPanelSlideListener(this)
}

Class SportsListOnBackPressedCallback yang telah selesai akan terlihat seperti berikut:

class SportsListOnBackPressedCallback(
   private val slidingPaneLayout: SlidingPaneLayout
): OnBackPressedCallback(slidingPaneLayout.isSlideable && slidingPaneLayout.isOpen),
  SlidingPaneLayout.PanelSlideListener{

   init {
       slidingPaneLayout.addPanelSlideListener(this)
   }

   override fun handleOnBackPressed() {
       slidingPaneLayout.closePane()
   }

   override fun onPanelSlide(panel: View, slideOffset: Float) {
   }

   override fun onPanelOpened(panel: View) {
       isEnabled = true
   }

   override fun onPanelClosed(panel: View) {
       isEnabled = false
   }
}

Mendaftarkan callback

Untuk melihat cara kerja callback, daftarkan callback menggunakan dispatcher, OnBackPressedDispatcher.

Class dasar untuk FragmentActivity memungkinkan Anda mengontrol perilaku tombol Kembali dengan menggunakan OnBackPressedDispatcher. OnBackPressedDispatcher mengontrol cara peristiwa tombol Kembali dikirim ke salah satu atau beberapa objek OnBackPressedCallback.

Tambahkan callback melalui metode addCallback(). Metode ini memerlukan LifecycleOwner. Metode ini memastikan bahwa OnBackPressedCallback hanya akan ditambahkan saat LifecycleOwner adalah Lifecycle.State.STARTED. Aktivitas atau fragmen ini juga akan menghapus callback yang terdaftar saat LifecycleOwner terkait diakhiri, yang mencegah kebocoran memori dan membuatnya cocok untuk digunakan dalam fragmen atau pemilik siklus proses lain yang memiliki masa berlaku lebih pendek.

Metode addCallback() juga menggunakan instance class callback sebagai parameter kedua. Anda akan mendaftarkan callback menggunakan langkah-langkah berikut:

  1. Di dalam file SportsListFragment, di dalam fungsi onViewCreated(), tepat di bawah deklarasi variabel binding, buat instance untuk SlidingPaneLayout dan tetapkan nilai binding.slidingPaneLayout ke dalamnya.
val slidingPaneLayout = binding.slidingPaneLayout
  1. Di file SportsListFragment, di dalam fungsi onViewCreated(), tepat di bawah deklarasi slidingPaneLayout, tambahkan kode berikut:
// Connect the SlidingPaneLayout to the system back button.
requireActivity().onBackPressedDispatcher.addCallback(
   viewLifecycleOwner,
   SportsListOnBackPressedCallback(slidingPaneLayout)
)

Kode di atas menggunakan addCallback(), meneruskan viewLifecycleOwner dan instance SportsListOnBackPressedCallback. Callback ini hanya aktif selama siklus proses fragmen.

  1. Kini saatnya menjalankan aplikasi di emulator dengan profil ponsel dan melihat cara kerja tombol kembali kustom.

33967fa8fde5b902.gif

9. Mode kunci

Saat panel daftar dan detail tumpang tindih pada layar yang lebih kecil seperti ponsel, pengguna dapat melakukan gestur geser ke kedua arah secara default, dengan bebas beralih antar dua panel bahkan saat tidak menggunakan navigasi gestur. Anda dapat mengunci atau membuka kunci panel detail dengan menyetel mode kunci SlidingPaneLayout.

  1. Di emulator dengan profil ponsel, coba geser panel detail keluar dari layar.
  2. Anda juga dapat menggeser di panel detail, coba lakukan ini sendiri.
  3. Ini bukan fitur yang diinginkan di aplikasi Olahraga. Sebaiknya kunci SlidingPaneLayout untuk mencegah pengguna menggeser ke dalam dan ke luar menggunakan gestur. Untuk menerapkannya, di metode onViewCreated(), di bawah definisi slidingPaneLayout, setel lockMode ke LOCK_MODE_LOCKED:
slidingPaneLayout.lockMode = SlidingPaneLayout.LOCK_MODE_LOCKED

Untuk mempelajari mode kunci lainnya lebih lanjut, lihat dokumentasi.

  1. Jalankan aplikasi sekali lagi, dan perhatikan bahwa panel detail sekarang dikunci.

Selamat, Anda telah menambahkan SlidingPaneLayout ke aplikasi!

10. Kode solusi

Kode solusi untuk codelab ini berada dalam project dan modul yang ditampilkan di bawah ini.

Untuk mendapatkan kode codelab ini dan membukanya di Android Studio, lakukan hal berikut.

Mendapatkan kode

  1. Klik URL yang diberikan. Tindakan ini akan membuka halaman GitHub project di browser.
  2. Di halaman GitHub project, klik tombol Code yang akan menampilkan dialog.

5b0a76c50478a73f.png

  1. Di dialog, klik tombol Download ZIP untuk menyimpan project di komputer. Tunggu download selesai.
  2. Temukan file di komputer Anda (mungkin di folder Downloads).
  3. Klik dua kali pada file ZIP untuk mengekstraknya. Tindakan ini akan membuat folder baru yang berisi file project.

Membuka project di Android Studio

  1. Mulai Android Studio.
  2. Di jendela Welcome to Android Studio, klik Open an existing Android Studio project.

36cc44fcf0f89a1d.png

Catatan: Jika Android Studio sudah terbuka, pilih opsi menu File > New > Import Project.

21f3eec988dcfbe9.png

  1. Di dialog Import Project, buka lokasi folder project yang telah diekstrak (kemungkinan ada di folder Downloads).
  2. Klik dua kali pada folder project tersebut.
  3. Tunggu Android Studio membuka project.
  4. Klik tombol Run 11c34fc5e516fb1c.png untuk mem-build dan menjalankan aplikasi. Pastikan aplikasi di-build seperti yang diharapkan.
  5. Cari file project di jendela alat Project untuk melihat cara aplikasi disiapkan.

11. Pelajari lebih lanjut