Dukungan untuk berbagai ukuran layar memungkinkan akses ke aplikasi Anda oleh berbagai perangkat dan jumlah pengguna terbanyak.
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 menampung ponsel, tablet, perangkat foldable, perangkat ChromeOS, orientasi potret dan lanskap, serta konfigurasi layar yang dapat diubah ukurannya seperti mode layar terpisah dan jendela desktop.
Tata letak responsif/adaptif berubah berdasarkan ruang tampilan yang tersedia. Perubahan bervariasi 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 tampilan yang berbeda dengan sebaik mungkin (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 di 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 aplikasi secara keseluruhan 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.
Pada 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. Mungkin ada lebih dari satu layar fisik, seperti dengan perangkat foldable. Dalam semua kasus ini, ukuran layar fisik tidak relevan dengan cara memutuskan cara menampilkan konten.
Sebagai gantinya, Anda harus membuat keputusan berdasarkan bagian layar sebenarnya yang dialokasikan ke aplikasi 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 tampilan yang tersedia, jumlah penanganan khusus yang diperlukan untuk mendukung platform seperti ChromeOS dan faktor bentuk seperti tablet dan perangkat foldable juga akan berkurang.
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 dirancang untuk menyeimbangkan kemudahan logika aplikasi dengan fleksibilitas agar aplikasi Anda dapat dioptimalkan 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 composable bertingkat.
@Composable fun MyApp( windowSizeClass: WindowSizeClass = currentWindowAdaptiveInfo().windowSizeClass ) { // Perform logic on the size class to decide whether to show the top app bar. val showTopAppBar = windowSizeClass.windowHeightSizeClass != WindowHeightSizeClass.COMPACT // MyScreen knows nothing about window sizes, and performs logic based on a 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 dengan 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 layar global secara implisit.
Bayangkan composable bertingkat yang mengimplementasikan tata letak detail daftar, yang dapat menampilkan satu panel atau dua panel secara berdampingan:
Keputusan detail daftar harus menjadi bagian dari tata letak keseluruhan untuk aplikasi, sehingga keputusan diteruskan dari composable tingkat konten:
@Composable fun AdaptivePane( showOnePane: Boolean, /* ... */ ) { if (showOnePane) { OnePane(/* ... */) } else { TwoPane(/* ... */) } }
Bagaimana jika Anda ingin composable 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 beberapa 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 apa pun akan ditampilkan, gunakan koleksi pengubah atau tata letak khusus agar tata letaknya responsif. Ini dapat semudah memiliki turunan yang mengisi semua ruang yang tersedia, atau menata letak turunan dengan beberapa kolom jika ada cukup ruang.
Jika Anda ingin mengubah item yang ditampilkan, gunakan
BoxWithConstraints
sebagai alternatif yang lebih efektif.BoxWithConstraints
menyediakan batasan pengukuran yang dapat Anda gunakan untuk memanggil composable yang berbeda berdasarkan ruang tampilan yang tersedia. Namun, hal ini memiliki konsekuensi, karenaBoxWithConstraints
menunda 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(/* ... */) } } } }
Memastikan semua data tersedia untuk berbagai ukuran tampilan
Saat menerapkan composable yang memanfaatkan ruang tampilan tambahan, Anda mungkin ingin menjadi efisien dan memuat data sebagai efek samping ukuran layar saat ini.
Namun, tindakan tersebut bertentangan dengan prinsip aliran data searah, dengan data dapat diangkat dan diberikan ke composable 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 layar (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 perubahan ukuran layar 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 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 layar
Video