Membuat tata letak daftar-detail

Daftar-detail adalah pola UI yang terdiri dari tata letak dua panel dengan satu panel menampilkan daftar item dan panel lain menampilkan detail item yang dipilih dari daftar.

Pola ini sangat berguna untuk aplikasi yang menyediakan informasi tentang elemen koleksi besar, misalnya, program email yang memiliki daftar email dan isi detail dari setiap pesan email. Daftar-detail juga dapat digunakan untuk jalur yang kurang penting seperti membagi aplikasi preferensi ke dalam daftar kategori dengan preferensi untuk setiap kategori panel detail.

Terapkan pola UI dengan ListDetailPaneScaffold

ListDetailPaneScaffold adalah composable yang menyederhanakan implementasi pola daftar-detail di aplikasi Anda. Scaffold daftar-detail dapat terdiri dari hingga tiga panel: panel daftar, panel detail, dan panel tambahan opsional. Tujuan scaffold menangani penghitungan ruang layar. Saat ukuran layar yang memadai tersedia, panel detail ditampilkan di samping panel daftar. Di layar kecil ukuran, scaffold secara otomatis beralih untuk menampilkan daftar atau layar penuh panel detail.

Panel detail yang ditampilkan di samping halaman daftar.
Gambar 1. Ketika ukuran layar yang cukup tersedia, detail ditampilkan di samping panel daftar.
Setelah item dipilih, panel detail akan mengambil alih seluruh layar.
Gambar 2. Jika ukuran layar dibatasi, panel detail (karena item telah dipilih) mengambil alih seluruh ruang.

Mendeklarasikan dependensi

ListDetailPaneScaffold adalah bagian dari tata letak adaptif Material 3 library.

Aplikasi Anda harus menyertakan dependensi untuk tiga library Material 3 terkait:

  • adaptif — Elemen penyusun tingkat rendah seperti HingeInfo dan Posture
  • Adaptive-layout — Tata letak adaptif seperti ListDetailPaneScaffold dan SupportingPaneScaffold
    • navigasi-adaptif — Composable untuk menavigasi di dalam dan antar-panel

Tambahkan dependensi ke file build.gradle aplikasi atau modul Anda:

Kotlin


implementation("androidx.compose.material3.adaptive:adaptive:1.0.0-alpha12")
implementation("androidx.compose.material3.adaptive:adaptive-layout:1.0.0-alpha12")
implementation("androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-alpha12")

Groovy


implementation 'androidx.compose.material3.adaptive:adaptive:1.0.0-alpha12'
implementation 'androidx.compose.material3.adaptive:adaptive-layout:1.0.0-alpha12'
implementation 'androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-alpha12'

Penggunaan dasar

Terapkan ListDetailPaneScaffold sebagai berikut:

  1. Gunakan class yang mewakili konten yang akan dipilih. Kelas ini harus Parcelable untuk mendukung penyimpanan dan memulihkan item daftar yang dipilih. Menggunakan paket kotlin-parcelize plugin untuk membuat kode untuk Anda.

    @Parcelize
    class MyItem(val id: Int) : Parcelable

  2. Membuat ThreePaneScaffoldNavigator dengan rememberListDetailPaneScaffoldNavigator, lalu tambahkan BackHandler. Ini navigator digunakan untuk berpindah antara panel daftar, detail, dan ekstra. Menurut mendeklarasikan tipe generik, navigator juga melacak status scaffold (yaitu, MyItem yang ditampilkan). Karena jenis ini parcelable, status dapat disimpan dan dipulihkan oleh navigator ke secara otomatis menangani perubahan konfigurasi. Tujuan BackHandler menyediakan dukungan untuk menavigasi kembali menggunakan {i>gesture <i}kembali sistem atau tombol. Perilaku yang diharapkan dari tombol kembali untuk ListDetailPaneScaffold bergantung pada ukuran jendela dan scaffold saat ini dengan sejumlah nilai. Jika ListDetailPaneScaffold dapat mendukung pengembalian dengan status saat ini, selanjutnya canNavigateBack() adalah true, yang mengaktifkan BackHandler.

    val navigator = rememberListDetailPaneScaffoldNavigator<MyItem>()
    
    BackHandler(navigator.canNavigateBack()) {
        navigator.navigateBack()
    }

  3. Teruskan scaffoldState dari navigator ke Composable ListDetailPaneScaffold.

    ListDetailPaneScaffold(
        directive = navigator.scaffoldDirective,
        value = navigator.scaffoldValue,
        // ...
    )

  4. Sediakan implementasi panel daftar Anda ke ListDetailPaneScaffold. Gunakan AnimatedPane untuk menerapkan animasi panel default selama navigasi. Kemudian gunakan ThreePaneScaffoldNavigator untuk membuka panel detail, ListDetailPaneScaffoldRole.Detail, dan tampilkan item yang diteruskan.

    ListDetailPaneScaffold(
        directive = navigator.scaffoldDirective,
        value = navigator.scaffoldValue,
        listPane = {
            AnimatedPane {
                MyList(
                    onItemClick = { item ->
                        // Navigate to the detail pane with the passed item
                        navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item)
                    }
                )
            }
        },
        // ...
    )

  5. Sertakan implementasi panel detail Anda di ListDetailPaneScaffold. Setelah navigasi selesai, currentDestination berisi panel yang yang dibuka oleh aplikasi, termasuk konten yang ditampilkan dalam panel. Tujuan Properti content adalah jenis yang sama dengan yang ditentukan dalam panggilan remember asli (MyItem dalam contoh ini), sehingga Anda juga dapat mengakses properti untuk semua data yang perlu Anda tampilkan.

    ListDetailPaneScaffold(
        directive = navigator.scaffoldDirective,
        value = navigator.scaffoldValue,
        listPane =
        // ...
        detailPane = {
            AnimatedPane {
                navigator.currentDestination?.content?.let {
                    MyDetails(it)
                }
            }
        },
    )

Setelah menerapkan langkah-langkah di atas, kode Anda akan terlihat seperti ini:

val navigator = rememberListDetailPaneScaffoldNavigator<MyItem>()

BackHandler(navigator.canNavigateBack()) {
    navigator.navigateBack()
}

ListDetailPaneScaffold(
    directive = navigator.scaffoldDirective,
    value = navigator.scaffoldValue,
    listPane = {
        AnimatedPane {
            MyList(
                onItemClick = { item ->
                    // Navigate to the detail pane with the passed item
                    navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item)
                },
            )
        }
    },
    detailPane = {
        AnimatedPane {
            // Show the detail pane content if selected item is available
            navigator.currentDestination?.content?.let {
                MyDetails(it)
            }
        }
    },
)