1. Pengantar
Dalam codelab ini, Anda akan mempelajari cara mem-build aplikasi adaptif untuk ponsel, tablet, dan perangkat foldable, serta cara meningkatkan keterjangkauan dengan Jetpack Compose. Anda juga akan mempelajari praktik terbaik untuk menggunakan komponen dan tema Material 3.
Sebelum mempelajarinya lebih lanjut, penting untuk memahami apa yang kami maksud dengan kemampuan beradaptasi.
Kemampuan adaptasi
UI untuk aplikasi Anda harus responsif agar dapat memperhitungkan berbagai ukuran jendela, orientasi, dan faktor bentuk. Tata letak adaptif berubah berdasarkan ruang layar yang tersedia untuknya. Perubahan ini bervariasi, mulai dari penyesuaian tata letak sederhana hingga mengisi ruang, memilih gaya navigasi masing-masing, sampai mengubah tata letak sepenuhnya untuk memanfaatkan ruang tambahan.
Untuk mempelajari lebih lanjut, lihat Desain adaptif.
Dalam codelab ini, Anda akan mempelajari cara menggunakan dan memikirkan kemampuan adaptasi saat menggunakan Jetpack Compose. Anda akan membuat aplikasi bernama Reply yang menunjukkan cara menerapkan kemampuan adaptasi untuk semua jenis layar, serta bagaimana kemampuan adaptasi dan keterjangkauan berfungsi bersama untuk memberi pengguna pengalaman yang optimal.
Yang akan Anda pelajari
- Cara mendesain aplikasi untuk menargetkan semua ukuran jendela dengan Jetpack Compose.
- Cara menargetkan aplikasi untuk berbagai perangkat foldable.
- Cara menggunakan berbagai jenis navigasi untuk meningkatkan keterjangkauan dan aksesibilitas.
- Cara menggunakan komponen Material 3 untuk memberikan pengalaman terbaik bagi setiap ukuran jendela.
Yang Anda butuhkan
- Versi stabil terbaru Android Studio.
- Perangkat virtual Android 13 yang dapat diubah ukurannya.
- Pengetahuan tentang Kotlin.
- Pemahaman dasar tentang Compose (seperti anotasi
@Composable
). - Pemahaman dasar tentang tata letak Compose (misalnya
Row
danColumn
). - Pemahaman dasar tentang pengubah (misalnya
Modifier.padding()
).
Anda akan menggunakan Emulator yang dapat diubah ukurannya untuk codelab ini, yang memungkinkan Anda beralih antara berbagai jenis perangkat dan ukuran jendela.
Jika Anda tidak terbiasa dengan Compose, sebaiknya ikuti codelab Dasar-dasar Jetpack Compose sebelum menyelesaikan codelab ini.
Yang akan Anda build
- Aplikasi klien email interaktif bernama Reply, yang menggunakan praktik terbaik untuk desain yang dapat disesuaikan, navigasi Material yang berbeda, dan penggunaan ruang layar yang optimal.
2. Memulai persiapan
Untuk mendapatkan kode bagi codelab ini, clone repositori GitHub dari command line:
git clone https://github.com/android/codelab-android-compose.git cd codelab-android-compose/AdaptiveUiCodelab
Atau, Anda dapat mendownload repositori sebagai file ZIP:
Sebaiknya Anda memulai dengan kode di cabang utama dan mengikuti codelab langkah demi langkah sesuai kemampuan Anda.
Membuka project di Android Studio
- Di jendela Welcome to Android Studio, pilih Open an Existing Project.
- Pilih folder
<Download Location>/AdaptiveUiCodelab
(pastikan Anda memilih direktoriAdaptiveUiCodelab
yang berisibuild.gradle
). - Setelah Android Studio mengimpor project, uji apakah Anda dapat menjalankan cabang
main
.
Mempelajari kode mulai
Kode cabang utama berisi paket ui
. Anda akan menggunakan file berikut dalam paket tersebut:
MainActivity.kt
- Aktivitas titik entri tempat Anda memulai aplikasi.ReplyApp.kt
- Berisi composable UI layar utama.ReplyHomeViewModel.kt
- Memberikan data dan status UI untuk konten aplikasi.ReplyListContent.kt
- Berisi composable untuk menyediakan daftar dan layar detail.
Jika Anda menjalankan aplikasi ini di emulator yang dapat diubah ukurannya dan mencoba berbagai jenis perangkat, seperti ponsel atau tablet, UI hanya akan diperluas ke ruang tertentu, bukan memanfaatkan ruang layar atau memberikan ergonomi keterjangkauan.
Anda akan memperbaruinya untuk memanfaatkan ruang layar, meningkatkan kegunaan, dan meningkatkan pengalaman pengguna secara keseluruhan.
3. Membuat aplikasi mudah disesuaikan
Bagian ini memperkenalkan apa artinya membuat aplikasi mudah disesuaikan, dan komponen apa yang disediakan Material 3 untuk membuatnya lebih mudah. Panduan ini juga membahas jenis layar dan status yang akan Anda targetkan, termasuk ponsel, tablet, tablet besar, dan perangkat foldable.
Anda akan memulai dengan membahas dasar-dasar ukuran jendela, postur lipat, dan berbagai jenis opsi navigasi. Kemudian, Anda dapat menggunakan API ini di aplikasi agar lebih adaptif.
Ukuran jendela
Perangkat Android tersedia dalam berbagai bentuk dan ukuran, dari ponsel, perangkat foldable, hingga tablet dan perangkat ChromeOS. Untuk mendukung sebanyak mungkin ukuran jendela, UI Anda harus responsif dan adaptif. Untuk membantu Anda menemukan nilai minimum yang tepat untuk mengubah UI aplikasi, kami telah menentukan nilai titik henti sementara yang membantu mengklasifikasikan perangkat ke dalam class ukuran yang telah ditentukan sebelumnya (ringkas, sedang, dan diperluas), yang disebut class ukuran jendela. Class ini adalah sekumpulan titik henti sementara area pandang tidak berubah yang membantu Anda mendesain, mengembangkan, dan menguji tata letak aplikasi yang responsif dan adaptif.
Kategori ini dipilih secara khusus untuk menyeimbangkan kesederhanaan tata letak dengan fleksibilitas untuk mengoptimalkan aplikasi Anda untuk kasus yang unik. Class ukuran jendela selalu ditentukan oleh ruang layar yang tersedia untuk aplikasi, yang mungkin bukan seluruh layar fisik untuk multitasking atau segmentasi lainnya.
Lebar dan tinggi diklasifikasikan secara terpisah, sehingga pada waktu tertentu aplikasi Anda akan memiliki dua class ukuran jendela, yaitu class untuk lebar dan class untuk tinggi. Lebar yang tersedia biasanya lebih penting daripada tinggi yang tersedia karena adanya scroll vertikal di mana saja, sehingga untuk kasus ini, Anda juga akan menggunakan class ukuran lebar.
Status lipat
Perangkat foldable menghadirkan lebih banyak situasi yang dapat disesuaikan oleh aplikasi Anda karena ukurannya yang bervariasi dan adanya engsel. Engsel dapat menutupi sebagian layar, sehingga area tersebut tidak cocok untuk menampilkan konten. Engsel juga dapat memisahkan, yang berarti ada dua layar fisik terpisah saat perangkat dibentangkan.
Selain itu, pengguna dapat melihat layar bagian dalam sementara engsel terbuka sebagian, menghasilkan postur fisik yang berbeda berdasarkan orientasi lipatan: postur mode di atas meja (lipatan horizontal, ditampilkan di sebelah kanan pada gambar di atas) dan postur buku (lipatan vertikal).
Baca selengkapnya tentang engsel dan postur lipat.
Semua hal ini adalah hal yang perlu dipertimbangkan saat menerapkan tata letak adaptif yang mendukung perangkat foldable.
Mendapatkan informasi adaptif
Library adaptive
Material3 menyediakan akses yang mudah ke informasi tentang jendela tempat aplikasi Anda berjalan.
- Tambahkan entri untuk artefak ini dan versinya ke file katalog versi:
gradle/libs.versions.toml
[versions]
material3Adaptive = "1.0.0"
[libraries]
androidx-material3-adaptive = { module = "androidx.compose.material3.adaptive:adaptive", version.ref = "material3Adaptive" }
- Dalam file build modul aplikasi, tambahkan dependensi library baru, lalu lakukan sinkronisasi Gradle:
app/build.gradle.kts
dependencies {
implementation(libs.androidx.material3.adaptive)
}
Sekarang, dalam cakupan composable apa pun, Anda dapat menggunakan currentWindowAdaptiveInfo()
untuk mendapatkan objek WindowAdaptiveInfo
yang berisi informasi seperti class ukuran jendela saat ini dan apakah perangkat dalam postur perangkat foldable seperti postur mode di atas meja.
Anda dapat mencobanya sekarang di MainActivity
.
- Di
onCreate()
di dalam blokReplyTheme
, dapatkan info adaptif jendela dan tampilkan class ukuran dalam composableText
. Anda dapat menambahkannya setelah elemenReplyApp()
:
MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ReplyTheme {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
ReplyApp(
replyHomeUIState = uiState,
onEmailClick = viewModel::setSelectedEmail
)
val adaptiveInfo = currentWindowAdaptiveInfo()
val sizeClassText =
"${adaptiveInfo.windowSizeClass.windowWidthSizeClass}\n" +
"${adaptiveInfo.windowSizeClass.windowHeightSizeClass}"
Text(
text = sizeClassText,
color = Color.Magenta,
modifier = Modifier.padding(
WindowInsets.safeDrawing.asPaddingValues()
)
)
}
}
}
Menjalankan aplikasi sekarang akan menampilkan class ukuran jendela yang dicetak di atas konten aplikasi. Jangan ragu untuk menjelajahi apa lagi yang disediakan di info adaptif jendela. Setelah itu, Anda dapat menghapus Text
ini karena mencakup konten aplikasi dan tidak diperlukan untuk langkah berikutnya.
4. Navigasi dinamis
Sekarang Anda akan menyesuaikan navigasi aplikasi seiring perubahan status dan ukuran perangkat agar aplikasi Anda lebih mudah digunakan.
Saat pengguna memegang ponsel, jari mereka biasanya berada di bagian bawah layar. Saat pengguna memegang perangkat foldable atau tablet yang terbuka, jari mereka biasanya berada di dekat sisi. Pengguna Anda harus dapat menavigasi atau memulai interaksi dengan aplikasi tanpa memerlukan posisi tangan yang ekstrem atau mengubah penempatan tangan mereka.
Saat Anda mendesain aplikasi dan memutuskan tempat untuk menempatkan elemen UI interaktif dalam tata letak, pertimbangkan implikasi ergonomis dari berbagai wilayah layar.
- Area mana yang nyaman untuk dijangkau sambil memegang perangkat?
- Area mana yang hanya dapat dijangkau dengan menjulurkan jari, yang mungkin tidak nyaman?
- Area mana yang sulit dijangkau atau jauh dari tempat pengguna memegang perangkat?
Navigasi adalah hal pertama yang digunakan pengguna untuk berinteraksi dan berisi tindakan yang sangat penting terkait perjalanan pengguna yang penting, sehingga harus ditempatkan di area yang paling mudah dijangkau. Library adaptif Material menyediakan beberapa komponen yang membantu Anda menerapkan navigasi, bergantung pada class ukuran jendela perangkat.
Navigasi bawah
Navigasi bawah sangat cocok untuk ukuran ringkas, karena secara alami kita memegang perangkat dengan ibu jari yang dapat dengan mudah menjangkau semua titik sentuh navigasi bawah. Gunakan navigasi ini setiap kali Anda memiliki ukuran perangkat yang ringkas atau perangkat foldable dalam status lipatan yang ringkas.
Kolom samping navigasi
Untuk ukuran jendela dengan lebar sedang, kolom samping navigasi ideal untuk keterjangkauan karena ibu jari kita secara alami berada di sepanjang sisi perangkat. Anda juga dapat menggabungkan kolom samping navigasi dengan panel navigasi untuk menampilkan informasi selengkapnya.
Panel navigasi
Panel navigasi menyediakan cara mudah guna melihat informasi mendetail untuk tab navigasi, dan mudah diakses saat Anda menggunakan tablet atau perangkat yang lebih besar. Ada dua jenis panel navigasi yang tersedia: panel navigasi modal dan panel navigasi permanen.
Panel navigasi modal
Anda dapat menggunakan panel navigasi modal untuk ponsel dan tablet berukuran ringkas hingga sedang karena dapat diperluas atau disembunyikan sebagai overlay pada konten. Terkadang, kolom samping ini dapat digabungkan dengan kolom samping navigasi.
Panel navigasi permanen
Anda dapat menggunakan panel navigasi permanen untuk navigasi tetap di tablet, Chromebook, dan desktop berukuran besar.
Menerapkan navigasi dinamis
Sekarang, Anda akan beralih antara berbagai jenis navigasi seiring perubahan status dan ukuran perangkat.
Saat ini, aplikasi selalu menampilkan NavigationBar
di bawah konten layar, terlepas dari status perangkat. Sebagai gantinya, Anda dapat menggunakan komponen NavigationSuiteScaffold
Material untuk beralih secara otomatis di antara berbagai komponen navigasi berdasarkan informasi seperti class ukuran jendela saat ini.
- Tambahkan dependensi Gradle untuk mendapatkan komponen ini dengan mengupdate katalog versi dan skrip build aplikasi, lalu jalankan sinkronisasi Gradle:
gradle/libs.versions.toml
[versions]
material3AdaptiveNavSuite = "1.3.0"
[libraries]
androidx-material3-adaptive-navigation-suite = { module = "androidx.compose.material3:material3-adaptive-navigation-suite", version.ref = "material3AdaptiveNavSuite" }
app/build.gradle.kts
dependencies {
implementation(libs.androidx.material3.adaptive.navigation.suite)
}
- Temukan fungsi composable
ReplyNavigationWrapper()
diReplyApp.kt
dan gantiColumn
dan kontennya denganNavigationSuiteScaffold
:
ReplyApp.kt
@Composable
private fun ReplyNavigationWrapperUI(
content: @Composable () -> Unit = {}
) {
var selectedDestination: ReplyDestination by remember {
mutableStateOf(ReplyDestination.Inbox)
}
NavigationSuiteScaffold(
navigationSuiteItems = {
ReplyDestination.entries.forEach {
item(
selected = it == selectedDestination,
onClick = { /*TODO update selection*/ },
icon = {
Icon(
imageVector = it.icon,
contentDescription = stringResource(it.labelRes)
)
},
label = {
Text(text = stringResource(it.labelRes))
},
)
}
}
) {
content()
}
}
Argumen navigationSuiteItems
adalah blok yang memungkinkan Anda menambahkan item menggunakan fungsi item()
, mirip dengan menambahkan item di LazyColumn
. Di dalam lambda terakhir, kode ini memanggil content()
yang diteruskan sebagai argumen ke ReplyNavigationWrapperUI()
.
Jalankan aplikasi di emulator dan coba ubah ukuran antara ponsel, perangkat foldable, dan tablet, dan Anda akan melihat menu navigasi berubah menjadi kolom samping navigasi dan kembali.
Pada jendela yang sangat lebar, seperti di tablet dalam mode lanskap, Anda mungkin ingin menampilkan panel navigasi permanen. NavigationSuiteScaffold
mendukung tampilan panel samping permanen, meskipun tidak ditampilkan dalam nilai WindowWidthSizeClass
saat ini. Namun, Anda dapat membuatnya melakukannya dengan sedikit perubahan.
- Tambahkan kode berikut tepat sebelum panggilan ke
NavigationSuiteScaffold
:
ReplyApp.kt
@Composable
private fun ReplyNavigationWrapperUI(
content: @Composable () -> Unit = {}
) {
var selectedDestination: ReplyDestination by remember {
mutableStateOf(ReplyDestination.Inbox)
}
val windowSize = with(LocalDensity.current) {
currentWindowSize().toSize().toDpSize()
}
val layoutType = if (windowSize.width >= 1200.dp) {
NavigationSuiteType.NavigationDrawer
} else {
NavigationSuiteScaffoldDefaults.calculateFromAdaptiveInfo(
currentWindowAdaptiveInfo()
)
}
NavigationSuiteScaffold(
layoutType = layoutType,
...
) {
content()
}
}
Kode ini pertama-tama mendapatkan ukuran jendela dan mengonversinya menjadi unit DP menggunakan currentWindowSize()
dan LocalDensity.current
, lalu membandingkan lebar jendela untuk menentukan jenis tata letak UI navigasi. Jika lebar jendela minimal 1200.dp
, jendela akan menggunakan NavigationSuiteType.NavigationDrawer
. Jika tidak, nilai ini akan kembali ke penghitungan default.
Saat Anda menjalankan aplikasi lagi di emulator yang dapat diubah ukurannya dan mencoba jenis yang berbeda, perhatikan bahwa setiap kali konfigurasi layar berubah atau Anda membuka perangkat foldable, navigasi akan berubah ke jenis yang sesuai untuk ukuran tersebut.
Selamat, Anda telah mempelajari berbagai jenis navigasi untuk mendukung berbagai jenis ukuran dan status jendela.
Di bagian berikutnya, Anda akan mempelajari cara memanfaatkan area layar yang tersisa, bukan meregangkan item daftar yang sama dari tepi ke tepi.
5. Penggunaan ruang layar
Tidak masalah apakah Anda menjalankan aplikasi di tablet kecil, perangkat yang dibentangkan, atau tablet besar, layar akan direntangkan untuk mengisi ruang yang tersisa. Anda ingin memastikan bahwa Anda dapat memanfaatkan ruang layar tersebut untuk menampilkan info selengkapnya, misalnya untuk aplikasi ini, menampilkan email dan rangkaian pesan kepada pengguna di halaman yang sama.
Material 3 menentukan tiga tata letak kanonis yang masing-masing memiliki konfigurasi untuk class ukuran jendela yang ringkas, sedang, dan diperluas. Tata letak kanonis Detail Daftar sangat cocok untuk kasus penggunaan ini, dan tersedia di compose sebagai ListDetailPaneScaffold
.
- Dapatkan komponen ini dengan menambahkan dependensi berikut dan melakukan sinkronisasi Gradle:
gradle/libs.versions.toml
[libraries]
androidx-material3-adaptive-layout = { module = "androidx.compose.material3.adaptive:adaptive-layout", version.ref = "material3Adaptive" }
androidx-material3-adaptive-navigation = { module = "androidx.compose.material3.adaptive:adaptive-navigation", version.ref = "material3Adaptive" }
app/build.gradle.kts
dependencies {
implementation(libs.androidx.material3.adaptive.layout)
implementation(libs.androidx.material3.adaptive.navigation)
}
- Temukan fungsi composable
ReplyAppContent()
diReplyApp.kt
, yang saat ini hanya menampilkan panel daftar dengan memanggilReplyListPane()
. Ganti implementasi ini denganListDetailPaneScaffold
dengan menyisipkan kode berikut. Karena ini adalah API eksperimental, Anda juga akan menambahkan anotasi@OptIn
pada fungsiReplyAppContent()
:
ReplyApp.kt
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
@Composable
fun ReplyAppContent(
replyHomeUIState: ReplyHomeUIState,
onEmailClick: (Email) -> Unit,
) {
val navigator = rememberListDetailPaneScaffoldNavigator<Long>()
ListDetailPaneScaffold(
directive = navigator.scaffoldDirective,
value = navigator.scaffoldValue,
listPane = {
ReplyListPane(replyHomeUIState, onEmailClick)
},
detailPane = {
ReplyDetailPane(replyHomeUIState.emails.first())
}
)
}
Kode ini terlebih dahulu membuat navigator menggunakan rememberListDetailPaneNavigator
. Navigator memberikan beberapa kontrol atas panel yang ditampilkan dan konten yang harus ditampilkan di panel tersebut, yang akan ditunjukkan nanti.
ListDetailPaneScaffold
akan menampilkan dua panel saat class ukuran lebar jendela diperluas. Jika tidak, panel ini akan menampilkan satu panel atau panel lainnya berdasarkan nilai yang diberikan untuk dua parameter: perintah scaffold dan nilai scaffold. Untuk mendapatkan perilaku default, kode ini menggunakan perintah scaffold dan nilai scaffold yang disediakan oleh navigator.
Parameter yang diperlukan lainnya adalah lambda composable untuk panel. ReplyListPane()
dan ReplyDetailPane()
(ditemukan di ReplyListContent.kt
) masing-masing digunakan untuk mengisi peran panel daftar dan detail. ReplyDetailPane()
mengharapkan argumen email, jadi untuk saat ini kode ini menggunakan email pertama dari daftar email di ReplyHomeUIState
.
Jalankan aplikasi dan alihkan tampilan emulator ke perangkat foldable atau tablet (Anda mungkin juga harus mengubah orientasi) untuk melihat tata letak dua panel. Tampilannya sudah jauh lebih baik dari sebelumnya.
Sekarang, mari kita bahas beberapa perilaku yang diinginkan dari layar ini. Saat pengguna mengetuk email di panel daftar, email tersebut akan ditampilkan di panel detail beserta semua balasan. Saat ini, aplikasi tidak melacak email mana yang dipilih, dan mengetuk item tidak akan melakukan apa pun. Tempat terbaik untuk menyimpan informasi ini adalah bersama dengan status UI lainnya di ReplyHomeUIState
.
- Buka
ReplyHomeViewModel.kt
dan temukan class dataReplyHomeUIState
. Tambahkan properti untuk email yang dipilih, dengan nilai defaultnull
:
ReplyHomeViewModel.kt
data class ReplyHomeUIState(
val emails : List<Email> = emptyList(),
val selectedEmail: Email? = null,
val loading: Boolean = false,
val error: String? = null
)
- Dalam file yang sama,
ReplyHomeViewModel
memiliki fungsisetSelectedEmail()
yang dipanggil saat pengguna mengetuk item daftar. Ubah fungsi ini untuk menyalin status UI dan merekam email yang dipilih:
ReplyHomeViewModel.kt
fun setSelectedEmail(email: Email) {
_uiState.update {
it.copy(selectedEmail = email)
}
}
Hal yang perlu dipertimbangkan adalah apa yang terjadi sebelum pengguna mengetuk item apa pun dan email yang dipilih adalah null
. Apa yang harus ditampilkan di panel detail? Ada beberapa cara untuk menangani kasus ini, seperti menampilkan item pertama dalam daftar secara default.
- Dalam file yang sama, ubah fungsi
observeEmails()
. Saat daftar email dimuat, jika status UI sebelumnya tidak memiliki email yang dipilih, tetapkan ke item pertama:
ReplyHomeViewModel.kt
private fun observeEmails() {
viewModelScope.launch {
emailsRepository.getAllEmails()
.catch { ex ->
_uiState.value = ReplyHomeUIState(error = ex.message)
}
.collect { emails ->
val currentSelection = _uiState.value.selectedEmail
_uiState.value = ReplyHomeUIState(
emails = emails,
selectedEmail = currentSelection ?: emails.first()
)
}
}
}
- Kembali ke
ReplyApp.kt
dan gunakan email yang dipilih, jika tersedia, untuk mengisi konten panel detail:
ReplyApp.kt
ListDetailPaneScaffold(
// ...
detailPane = {
if (replyHomeUIState.selectedEmail != null) {
ReplyDetailPane(replyHomeUIState.selectedEmail)
}
}
)
Jalankan lagi aplikasi dan alihkan emulator ke ukuran tablet, dan lihat bahwa mengetuk item daftar akan memperbarui konten panel detail.
Hal ini berfungsi dengan baik saat kedua panel terlihat, tetapi jika jendela hanya memiliki ruang untuk menampilkan satu panel, sepertinya tidak ada yang terjadi saat Anda mengetuk item. Coba alihkan tampilan emulator ke ponsel, atau perangkat foldable dalam mode potret, dan perhatikan bahwa hanya panel daftar yang terlihat bahkan setelah mengetuk item. Hal ini karena meskipun email yang dipilih telah diupdate, ListDetailPaneScaffold
akan menjaga fokus pada panel daftar dalam konfigurasi ini.
- Untuk memperbaikinya, masukkan kode berikut sebagai lambda yang diteruskan ke
ReplyListPane
:
ReplyApp.kt
ListDetailPaneScaffold(
// ...
listPane = {
ReplyListPane(
replyHomeUIState = replyHomeUIState,
onEmailClick = { email ->
onEmailClick(email)
navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, email.id)
}
)
},
// ...
)
Lambda ini menggunakan navigator yang dibuat sebelumnya untuk menambahkan perilaku tambahan saat item diklik. Fungsi ini akan memanggil lambda asli yang diteruskan ke fungsi ini, lalu juga memanggil navigator.navigateTo()
yang menentukan panel mana yang akan ditampilkan. Setiap panel dalam scaffold memiliki peran yang terkait dengannya, dan untuk panel detail, peran tersebut adalah ListDetailPaneScaffoldRole.Detail
. Pada jendela yang lebih kecil, hal ini akan memberikan tampilan bahwa aplikasi telah menavigasi ke depan.
Aplikasi juga perlu menangani apa yang terjadi saat pengguna menekan tombol kembali dari panel detail, dan perilaku ini akan berbeda bergantung pada apakah ada satu panel atau dua panel yang terlihat.
- Dukung navigasi kembali dengan menambahkan kode berikut.
ReplyApp.kt
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
@Composable
fun ReplyAppContent(
replyHomeUIState: ReplyHomeUIState,
onEmailClick: (Email) -> Unit,
) {
val navigator = rememberListDetailPaneScaffoldNavigator<Long>()
BackHandler(navigator.canNavigateBack()) {
navigator.navigateBack()
}
ListDetailPaneScaffold(
directive = navigator.scaffoldDirective,
value = navigator.scaffoldValue,
listPane = {
AnimatedPane {
ReplyListPane(
replyHomeUIState = replyHomeUIState,
onEmailClick = { email ->
onEmailClick(email)
navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, email.id)
}
)
}
},
detailPane = {
AnimatedPane {
if (replyHomeUIState.selectedEmail != null) {
ReplyDetailPane(replyHomeUIState.selectedEmail)
}
}
}
)
}
Navigator mengetahui status lengkap ListDetailPaneScaffold
, apakah navigasi kembali dapat dilakukan, dan apa yang harus dilakukan dalam semua skenario ini. Kode ini membuat BackHandler
yang diaktifkan setiap kali navigator dapat menavigasi kembali, dan di dalam lambda memanggil navigateBack()
. Selain itu, untuk membuat transisi antarpanel jauh lebih lancar, setiap panel digabungkan dalam composable AnimatedPane()
.
Jalankan kembali aplikasi pada emulator yang dapat diubah ukurannya untuk semua jenis perangkat dan perhatikan bahwa setiap kali konfigurasi layar berubah, atau Anda membuka perangkat foldable, navigasi dan konten layar akan berubah secara dinamis sebagai respons terhadap perubahan status perangkat. Coba juga ketuk email di panel daftar dan lihat perilaku tata letak di berbagai layar, yang menampilkan kedua panel secara berdampingan atau menganimasikan di antara keduanya dengan lancar.
Selamat, Anda telah berhasil membuat aplikasi yang dapat disesuaikan untuk semua jenis status dan ukuran perangkat. Coba dan jalankan aplikasi ini di perangkat foldable, tablet, atau perangkat seluler lainnya.
6. Selamat
Selamat! Anda telah berhasil menyelesaikan codelab ini dan mempelajari cara membuat aplikasi menjadi adaptif dengan Jetpack Compose.
Anda telah mempelajari cara memeriksa ukuran dan status lipat perangkat, serta mengupdate UI, navigasi, dan fungsi lainnya dari aplikasi Anda. Anda juga telah mempelajari bagaimana kemampuan adaptasi meningkatkan keterjangkauan dan meningkatkan pengalaman pengguna.
Apa langkah selanjutnya?
Lihat codelab lainnya di jalur Compose.
Aplikasi contoh
- Contoh compose adalah kumpulan banyak aplikasi yang menggabungkan praktik terbaik yang dijelaskan dalam codelab.