Dukungan untuk berbagai ukuran layar memungkinkan akses ke aplikasi Anda oleh berbagai macam perangkat dan sejumlah besar pengguna.
Untuk mendukung sebanyak mungkin ukuran tampilan—baik layar perangkat yang berbeda atau jendela aplikasi yang berbeda dalam mode multi-aplikasi—desain tata letak aplikasi Anda agar responsif dan adaptif. Tata letak responsif/adaptif memberikan pengalaman pengguna yang dioptimalkan terlepas dari ukuran layar, sehingga memungkinkan aplikasi Anda mengakomodasi ponsel, tablet, perangkat foldable, perangkat ChromeOS, orientasi potret dan lanskap, serta konfigurasi layar yang dapat diubah ukurannya seperti mode layar terpisah dan penyesuaian jendela desktop.
Tata letak responsif/adaptif berubah berdasarkan ruang tampilan yang tersedia. Perubahan berkisar dari penyesuaian tata letak kecil yang mengisi ruang (desain responsif) hingga mengganti satu tata letak dengan tata letak lain sepenuhnya sehingga aplikasi Anda dapat mengakomodasi ukuran layar yang berbeda dengan sebaik-baiknya (desain adaptif).
Sebagai toolkit UI deklaratif, Jetpack Compose sangat ideal untuk mendesain dan mengimplementasikan tata letak yang berubah secara dinamis untuk merender konten secara berbeda pada berbagai ukuran layar.
Membuat perubahan tata letak yang besar untuk composable tingkat konten secara eksplisit
Composable tingkat aplikasi dan tingkat konten menempati semua ruang tampilan yang tersedia untuk aplikasi Anda. Untuk jenis composable ini, sebaiknya ubah tata letak keseluruhan aplikasi Anda di layar besar.
Hindari penggunaan nilai hardware fisik untuk membuat keputusan tata letak. Anda mungkin ingin membuat keputusan berdasarkan nilai nyata yang tetap (Apakah perangkat ini berupa tablet? Apakah layar fisik memiliki rasio aspek tertentu?), tetapi jawaban atas pertanyaan ini mungkin tidak berguna untuk menentukan ruang yang tersedia untuk UI Anda.
Di tablet, aplikasi mungkin berjalan dalam mode multi-aplikasi, yang berarti aplikasi mungkin memisahkan layar dengan aplikasi lain. Dalam mode jendela desktop atau di ChromeOS, aplikasi mungkin berada di jendela yang dapat diubah ukurannya. Bahkan mungkin ada lebih dari satu layar fisik, seperti pada perangkat foldable. Di semua kasus ini, ukuran layar fisik tidak relevan dengan memutuskan cara menampilkan konten.
Sebagai gantinya, buat keputusan berdasarkan bagian layar sebenarnya yang dialokasikan ke aplikasi Anda yang dijelaskan oleh metrik jendela saat ini yang disediakan oleh library WindowManager Jetpack. Untuk contoh cara menggunakan WindowManager di aplikasi Compose, lihat contoh JetNews.
Dengan menjadikan tata letak Anda adaptif dengan ruang layar yang tersedia juga akan mengurangi jumlah penanganan khusus yang diperlukan untuk mendukung platform seperti ChromeOS dan faktor bentuk seperti tablet dan perangkat foldable.
Setelah Anda menentukan metrik ruang yang tersedia untuk aplikasi, konversikan ukuran mentah menjadi class ukuran jendela seperti yang dijelaskan dalam Menggunakan class ukuran jendela. Class ukuran jendela adalah titik henti sementara yang didesain untuk menyeimbangkan kesederhanaan logika aplikasi dengan fleksibilitas untuk mengoptimalkan aplikasi Anda untuk sebagian besar ukuran tampilan.
Class ukuran jendela mengacu pada keseluruhan jendela aplikasi Anda, jadi gunakan class untuk keputusan tata letak yang memengaruhi tata letak aplikasi secara keseluruhan. Anda dapat meneruskan class ukuran jendela ke bawah sebagai status, atau Anda dapat menjalankan logika tambahan untuk membuat status turunan guna diteruskan ke komponen bertingkat.
@Composable fun MyApp( windowSizeClass: WindowSizeClass = currentWindowAdaptiveInfo().windowSizeClass ) { // Decide whether to show the top app bar based on window size class. val showTopAppBar = windowSizeClass.isHeightAtLeastBreakpoint(WindowSizeClass.HEIGHT_DP_MEDIUM_LOWER_BOUND) // MyScreen logic is based on the showTopAppBar boolean flag. MyScreen( showTopAppBar = showTopAppBar, /* ... */ ) }
Pendekatan berlapis membatasi logika ukuran tampilan ke satu lokasi, bukan menyebarkannya di aplikasi Anda di banyak tempat yang harus terus disinkronkan. Satu lokasi menghasilkan status, yang dapat secara eksplisit diteruskan ke composable lain seperti status aplikasi lainnya. Meneruskan status secara eksplisit menyederhanakan composable individual karena composable menggunakan class ukuran jendela atau konfigurasi yang ditentukan bersama data lainnya.
Composable bertingkat yang fleksibel dapat digunakan kembali
Composable lebih dapat digunakan kembali saat dapat ditempatkan di berbagai tempat. Jika composable harus ditempatkan di lokasi tertentu dengan ukuran tertentu, composable tersebut kemungkinan tidak dapat digunakan kembali dalam konteks lain. Ini juga berarti bahwa composable individual yang dapat digunakan kembali harus menghindari ketergantungan pada informasi ukuran tampilan global secara implisit.
Bayangkan composable bertingkat yang mengimplementasikan tata letak detail daftar, yang dapat menampilkan satu panel atau dua panel secara berdampingan:
Keputusan daftar-detail harus menjadi bagian dari tata letak keseluruhan untuk aplikasi, jadi keputusan diteruskan dari composable tingkat konten:
@Composable fun AdaptivePane( showOnePane: Boolean, /* ... */ ) { if (showOnePane) { OnePane(/* ... */) } else { TwoPane(/* ... */) } }
Bagaimana jika Anda menginginkan composable dapat mengubah tata letaknya secara independen berdasarkan ruang tampilan yang tersedia, misalnya, kartu yang menampilkan detail tambahan jika ruangnya memungkinkan? Anda ingin menjalankan beberapa logika berdasarkan ukuran layar yang tersedia, tetapi ukuran mana yang spesifik?
Hindari mencoba menggunakan ukuran layar perangkat yang sebenarnya. Hal ini tidak akan akurat untuk berbagai jenis layar dan juga tidak akan akurat jika aplikasi tidak dalam mode layar penuh.
Karena composable ini bukan composable tingkat konten, jangan gunakan metrik jendela saat ini secara langsung.
Jika komponen ditempatkan dengan padding (seperti dengan inset), atau jika aplikasi menyertakan komponen seperti kolom samping navigasi atau panel aplikasi, jumlah ruang tampilan yang tersedia untuk composable mungkin berbeda secara signifikan dari keseluruhan ruang yang tersedia untuk aplikasi.
Gunakan lebar yang benar-benar disediakan composable untuk merendernya sendiri. Anda memiliki dua opsi untuk mendapatkan lebar tersebut:
Jika Anda ingin mengubah lokasi atau cara konten ditampilkan, gunakan kumpulan pengubah atau tata letak kustom untuk membuat tata letak responsif. Ini bisa sesederhana memiliki turunan yang mengisi semua ruang yang tersedia, atau menata letak turunan dengan beberapa kolom jika ada cukup ruang.
Jika ingin mengubah item yang ditampilkan, gunakan
BoxWithConstraintssebagai alternatif yang lebih efektif.BoxWithConstraintsmenyediakan batasan pengukuran yang dapat Anda gunakan untuk memanggil berbagai composable berdasarkan ruang tampilan yang tersedia. Namun, hal ini memiliki konsekuensi, karenaBoxWithConstraintsmenangguhkan komposisi hingga fase tata letak, saat batasan ini diketahui, sehingga menyebabkan lebih banyak pekerjaan yang harus dilakukan selama tata letak.
@Composable fun Card(/* ... */) { BoxWithConstraints { if (maxWidth < 400.dp) { Column { Image(/* ... */) Title(/* ... */) } } else { Row { Column { Title(/* ... */) Description(/* ... */) } Image(/* ... */) } } } }
Menyediakan semua data untuk berbagai ukuran tampilan
Saat mengimplementasikan komponen yang memanfaatkan ruang tampilan tambahan, Anda mungkin ingin menjadi efisien dan memuat data sebagai efek samping dari ukuran tampilan saat ini.
Namun, tindakan ini bertentangan dengan prinsip aliran data searah, dengan data dapat diangkat dan diberikan ke komponen untuk dirender dengan tepat. Data yang cukup harus diberikan ke composable agar composable selalu memiliki konten yang cukup untuk ukuran tampilan apa pun, meskipun beberapa bagian konten mungkin tidak selalu digunakan.
@Composable fun Card( imageUrl: String, title: String, description: String ) { BoxWithConstraints { if (maxWidth < 400.dp) { Column { Image(imageUrl) Title(title) } } else { Row { Column { Title(title) Description(description) } Image(imageUrl) } } } }
Berdasarkan contoh Card, perhatikan bahwa description selalu diteruskan ke
Card. Meskipun description hanya digunakan saat lebar mengizinkan
untuk menampilkannya, Card selalu memerlukan description, terlepas dari
lebar yang tersedia.
Selalu meneruskan konten yang memadai akan menyederhanakan tata letak adaptif dengan membuatnya kurang stateful dan menghindari pemicu efek samping saat beralih antar-ukuran tampilan (yang dapat terjadi karena perubahan ukuran jendela, perubahan orientasi, atau lipatan dan lipatan perangkat).
Prinsip ini juga memungkinkan untuk mempertahankan status di seluruh perubahan tata letak. Dengan menarik informasi yang mungkin tidak digunakan di semua ukuran tampilan, Anda dapat mempertahankan status aplikasi saat ukuran tata letak berubah.
Misalnya, Anda dapat mengangkat flag boolean showMore sehingga status aplikasi dipertahankan saat pengubahan ukuran tampilan menyebabkan tata letak beralih antara menyembunyikan dan menampilkan konten:
@Composable fun Card( imageUrl: String, title: String, description: String ) { var showMore by remember { mutableStateOf(false) } BoxWithConstraints { if (maxWidth < 400.dp) { Column { Image(imageUrl) Title(title) } } else { Row { Column { Title(title) Description( description = description, showMore = showMore, onShowMoreToggled = { newValue -> showMore = newValue } ) } Image(imageUrl) } } } }
Pelajari lebih lanjut
Untuk mempelajari tata letak adaptif di Compose lebih lanjut, lihat referensi berikut:
Aplikasi contoh
- CanonicalLayouts adalah repositori pola desain yang telah terbukti yang memberikan pengalaman pengguna yang optimal di layar besar
- JetNews menunjukkan cara mendesain aplikasi yang menyesuaikan UI-nya untuk memanfaatkan ruang tampilan yang tersedia
- Reply adalah contoh adaptif untuk mendukung perangkat seluler, tablet, dan perangkat foldable
- Now in Android adalah aplikasi yang menggunakan tata letak adaptif untuk mendukung berbagai ukuran tampilan
Video