Tata letak dasar di Compose

1. Pengantar

Sebagai toolkit UI, Compose memudahkan Anda menerapkan desain aplikasi. Anda mendeskripsikan tampilan UI yang Anda inginkan, dan Compose akan menggambarnya di layar. Codelab ini mengajarkan cara menulis UI Compose. Hal ini mengasumsikan bahwa Anda memahami konsep yang diajarkan di codelab dasar-dasar, jadi pastikan Anda menyelesaikan codelab tersebut terlebih dahulu. Di codelab Dasar, Anda telah mempelajari cara mengimplementasikan tata letak sederhana menggunakan Surfaces, Rows, dan Columns. Anda juga meningkatkan tata letak ini dengan pengubah seperti padding, fillMaxWidth, dan size.

Dalam codelab ini, Anda akan menerapkan tata letak yang lebih realistis dan kompleks untuk mempelajari berbagai composable siap pakai dan pengubah di sepanjang proses. Setelah menyelesaikan codelab ini, Anda seharusnya dapat mengubah desain aplikasi dasar menjadi kode yang berfungsi.

Codelab ini tidak menambahkan perilaku aktual ke aplikasi. Sebagai gantinya, untuk mempelajari status dan interaksi, selesaikan codelab Status dalam Compose.

Untuk mendapatkan dukungan lebih lanjut saat Anda mempelajari codelab ini, lihat kode berikut:

Yang akan Anda pelajari

Dalam codelab ini, Anda akan mempelajari:

  • Cara pengubah membantu Anda meningkatkan composable.
  • Cara komponen tata letak standar seperti Column dan LazyRow memosisikan composable turunan.
  • Cara perataan dan pengaturan mengubah posisi composable turunan di induknya.
  • Cara composable Material seperti Scaffold dan Navigasi Bawah membantu Anda membuat tata letak komprehensif.
  • Cara membangun composable fleksibel menggunakan API slot.
  • Cara membangun tata letak untuk berbagai konfigurasi layar.

Yang akan Anda butuhkan

Yang akan Anda build

Dalam codelab ini, Anda akan menerapkan desain aplikasi yang realistis berdasarkan tiruan yang disediakan oleh desainer. MySoothe adalah aplikasi kesehatan yang mencatat berbagai cara untuk meningkatkan kesehatan tubuh dan pikiran. Aplikasi ini berisi bagian yang mencantumkan koleksi favorit Anda dan bagian dengan latihan fisik. Tampilan aplikasi akan terlihat seperti berikut:

Versi potret aplikasi

Versi lanskap aplikasi

2. Mempersiapkan

Pada langkah ini, Anda akan mendownload kode yang berisi tema dan beberapa penyiapan dasar.

Mendapatkan kode

Kode untuk codelab ini dapat ditemukan di repositori GitHub codelab-android-compose. Untuk melakukan clone kode ini, jalankan:

$ git clone https://github.com/android/codelab-android-compose

Atau, Anda dapat mendownload dua file ZIP:

Melihat kode

Kode yang didownload berisi kode untuk semua codelab Compose yang tersedia. Untuk menyelesaikan codelab ini, buka project BasicLayoutsCodelab di dalam Android Studio.

Sebaiknya Anda memulai dengan kode di cabang main dan mengikuti codelab langkah demi langkah sesuai kemampuan Anda.

3. Mulai dengan rencana

Kita akan mulai dengan menerapkan desain potret aplikasi - mari kita pelajari lebih lanjut:

desain potret

Saat Anda diminta menerapkan desain, cara yang baik untuk memulai adalah dengan memahami strukturnya dengan jelas. Jangan langsung memulai coding, tetapi analisis desainnya. Bagaimana cara membagi UI ini menjadi beberapa bagian yang dapat digunakan kembali?

Jadi, mari kita coba desain kami. Pada level abstraksi tertinggi, kita dapat membagi desain ini menjadi dua bagian:

  • Konten layar.
  • Navigasi bawah.

pengelompokan desain aplikasi

Melihat perincian, konten layar berisi tiga sub-bagian:

  • Kotak penelusuran.
  • Bagian bernama "Align your body".
  • Bagian yang disebut "Favorite collections".

pengelompokan desain aplikasi

Di dalam setiap bagian, Anda juga dapat melihat beberapa komponen dengan level lebih rendah yang digunakan kembali:

  • Elemen "align your body" yang ditampilkan dalam baris yang dapat di-scroll secara horizontal.

elemen align your body

  • Kartu "favorite collection" (koleksi favorit) yang ditampilkan dalam petak yang dapat di-scroll secara horizontal.

kartu koleksi favorit

Setelah menganalisis desain, Anda dapat mulai menerapkan composable untuk setiap bagian UI yang diidentifikasi. Mulai dengan composable level terendah dan terus gabungkan ke dalam composable yang lebih kompleks. Di akhir codelab, aplikasi baru Anda akan terlihat seperti desain yang disediakan.

4. Kotak penelusuran - Pengubah

Elemen pertama yang berubah menjadi composable adalah Kotak penelusuran. Mari perhatikan kembali desainnya:

kotak penelusuran

Berdasarkan screenshot ini saja, akan sangat sulit untuk menerapkan desain ini dengan cara yang sempurna untuk piksel. Umumnya, seorang desainer menyampaikan lebih banyak informasi tentang desainnya. Mereka dapat memberi Anda akses ke alat desain mereka, atau membagikan apa yang disebut desain redlining. Dalam hal ini, desainer kami menyerahkan desain redlining, yang dapat Anda gunakan untuk membaca semua nilai ukuran. Desain ditampilkan dengan overlay petak 8 dp, sehingga Anda dapat dengan mudah melihat seberapa banyak ruang antara dan di sekitar elemen. Selain itu, beberapa spasi ditambahkan secara eksplisit untuk memperjelas ukuran tertentu.

garis merah kotak penelusuran

Anda dapat melihat bahwa kotak penelusuran harus memiliki tinggi 56 piksel kepadatan mandiri. Class ini juga harus mengisi lebar penuh induknya.

Untuk menerapkan kotak penelusuran, gunakan komponen Material yang disebut Kolom teks. Library Compose Material berisi composable yang disebut TextField, yang merupakan implementasi komponen Material ini.

Mulai dengan implementasi TextField dasar. Di code base, buka MainActivity.kt dan telusuri composable SearchBar.

Di dalam composable yang disebut SearchBar, tulis implementasi TextField dasar:

import androidx.compose.material3.TextField

@Composable
fun SearchBar(
   modifier: Modifier = Modifier
) {
   TextField(
       value = "",
       onValueChange = {},
       modifier = modifier
   )
}

Beberapa hal yang perlu diperhatikan:

  • Anda melakukan hardcode pada nilai kolom teks, dan callback onValueChange tidak melakukan apa pun. Karena ini adalah codelab yang berfokus pada tata letak, Anda mengabaikan apa pun yang berkaitan dengan status.
  • Fungsi composable SearchBar menerima parameter modifier dan meneruskannya ke TextField. Ini merupakan praktik terbaik sesuai pedoman Compose. Hal ini memungkinkan pemanggil metode untuk mengubah tampilan & nuansa composable, yang membuatnya lebih fleksibel dan dapat digunakan kembali. Anda akan melanjutkan praktik terbaik ini untuk semua composable di codelab ini.

Mari kita lihat pratinjau composable ini. Ingat bahwa Anda dapat menggunakan fungsi Pratinjau di Android Studio untuk melakukan iterasi dengan cepat pada setiap composable. MainActivity.kt berisi pratinjau untuk semua composable yang akan Anda build dalam codelab ini. Dalam hal ini, metode SearchBarPreview merender composable SearchBar, dengan beberapa latar belakang dan padding untuk memberikan sedikit lebih banyak konteks. Dengan implementasi yang baru saja Anda tambahkan, tampilannya akan terlihat seperti ini:

pratinjau kotak penelusuran

Ada beberapa hal yang hilang. Pertama, mari perbaiki ukuran composable menggunakan pengubah.

Saat menulis composable, Anda menggunakan pengubah untuk:

  • Mengubah ukuran, tata letak, perilaku, dan tampilan composable.
  • Menambahkan informasi, seperti label aksesibilitas.
  • Memproses input pengguna.
  • Menambahkan interaksi tingkat tinggi, seperti membuat elemen yang dapat diklik, dapat di-scroll, dapat ditarik, atau dapat di-zoom.

Setiap composable yang Anda panggil memiliki parameter modifier yang dapat ditetapkan untuk menyesuaikan tampilan, nuansa, dan perilaku composable tersebut. Saat menetapkan pengubah, Anda dapat merangkai beberapa metode pengubah untuk membuat adaptasi yang lebih kompleks.

Dalam hal ini, kotak penelusuran harus berukuran minimal 56 dp, dan mengisi lebar induknya. Untuk menemukan pengubah yang tepat, Anda dapat melihat daftar pengubah dan melihat bagian Ukuran. Untuk tinggi, Anda dapat menggunakan pengubah heightIn. Ini memastikan bahwa composable memiliki tinggi minimum tertentu. Namun, ukuran halaman dapat menjadi lebih besar misalnya, jika pengguna memperbesar ukuran font sistem. Untuk lebar, Anda dapat menggunakan pengubah fillMaxWidth. Pengubah ini memastikan bahwa kotak penelusuran menggunakan semua ruang horizontal dari induknya.

Update pengubah agar cocok dengan kode di bawah ini:

import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.material3.TextField

@Composable
fun SearchBar(
   modifier: Modifier = Modifier
) {
   TextField(
       value = "",
       onValueChange = {},
       modifier = modifier
           .fillMaxWidth()
           .heightIn(min = 56.dp)
   )
}

Dalam hal ini, karena satu pengubah memengaruhi lebar, dan yang lainnya memengaruhi tinggi, urutan pengubah ini tidak berpengaruh.

Anda juga harus menetapkan beberapa parameter TextField. Cobalah untuk membuat composable terlihat seperti desain dengan menetapkan nilai parameter. Berikut desainnya lagi sebagai referensi:

kotak penelusuran

Berikut adalah langkah-langkah yang sebaiknya Anda lakukan untuk mengupdate implementasi:

  • Tambahkan ikon penelusuran. TextField berisi parameter leadingIcon yang menerima composable lain. Di dalam, Anda dapat menetapkan Icon, yang dalam hal ini berupa ikon Search. Pastikan untuk menggunakan impor Icon Compose yang tepat.
  • Anda dapat menggunakan TextFieldDefaults.textFieldColors untuk mengganti warna tertentu. Setel focusedContainerColor dan unfocusedContainerColor kolom teks ke warna surface MaterialTheme.
  • Tambahkan teks placeholder "Search" (Anda dapat menemukannya sebagai resource string R.string.placeholder_search).

Setelah selesai, composable Anda akan terlihat seperti ini:

import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.ui.res.stringResource
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Search

@Composable
fun SearchBar(
   modifier: Modifier = Modifier
) {
   TextField(
       value = "",
       onValueChange = {},
       leadingIcon = {
           Icon(
               imageVector = Icons.Default.Search,
               contentDescription = null
           )
       },
       colors = TextFieldDefaults.colors(
           unfocusedContainerColor = MaterialTheme.colorScheme.surface,
           focusedContainerColor = MaterialTheme.colorScheme.surface
       ),
       placeholder = {
           Text(stringResource(R.string.placeholder_search))
       },
       modifier = modifier
           .fillMaxWidth()
           .heightIn(min = 56.dp)
   )
}

kotak penelusuran

Perhatikan bahwa:

  • Anda menambahkan leadingIcon yang menampilkan ikon penelusuran. Ikon ini tidak memerlukan deskripsi konten, karena placeholder kolom teks telah menjelaskan arti kolom teks. Ingat bahwa deskripsi konten biasanya digunakan untuk tujuan aksesibilitas dan memberikan representasi tekstual dari gambar atau ikon aplikasi kepada pengguna.
  • Untuk menyesuaikan warna latar belakang kolom teks, Anda harus menyetel properti colors. Sebagai ganti parameter terpisah untuk setiap warna, composable dapat berisi satu parameter gabungan. Di sini, Anda meneruskan salinan class data TextFieldDefaults, tempat Anda hanya mengubah warna yang berbeda. Dalam hal ini, itu hanya warna unfocusedContainerColor dan focusedContainerColor.

Pada langkah ini, Anda telah melihat cara menggunakan parameter dan pengubah composable untuk mengubah tampilan dan nuansa composable. Ini berlaku untuk composable yang disediakan oleh library Compose dan Material, serta yang Anda tulis sendiri. Anda harus selalu memikirkan penyediaan parameter untuk menyesuaikan composable yang ditulis. Anda juga harus menambahkan properti modifier sehingga tampilan dan nuansa composable dapat disesuaikan dari luar.

5. Align your body - Perataan

Composable berikutnya yang akan Anda terapkan adalah elemen "Selaraskan tubuh Anda". Mari kita lihat desainnya, termasuk desain garis merah di sampingnya:

komponen align your body

garis merah align your body

Desain garis merah kini juga berisi spasi berorientasi dasar pengukuran. Berikut adalah informasi yang kami peroleh dari laporan tersebut:

  • Gambar harus berukuran 88 dp.
  • Spasi antara dasar pengukuran teks dan gambar harus 24dp.
  • Jarak antara dasar pengukuran dan bagian bawah elemen harus 8 dp.
  • Teks harus bergaya tipografi bodyMedium.

Untuk menerapkan composable ini, Anda memerlukan composable Image dan Text. Keduanya perlu disertakan dalam Column, sehingga diposisikan di bawah satu sama lain.

Temukan composable AlignYourBodyElement dalam kode Anda dan update kontennya dengan implementasi dasar ini:

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.ui.res.painterResource

@Composable
fun AlignYourBodyElement(
   modifier: Modifier = Modifier
) {
   Column(
       modifier = modifier
   ) {
       Image(
           painter = painterResource(R.drawable.ab1_inversions),
           contentDescription = null
       )
       Text(text = stringResource(R.string.ab1_inversions))
   }
}

Perhatikan bahwa:

  • Anda menyetel contentDescription gambar ke null, karena gambar ini hanya bersifat dekoratif. Teks di bawah gambar menjelaskan maknanya secara memadai, sehingga gambar tidak memerlukan deskripsi tambahan.
  • Anda menggunakan gambar dan teks hard code. Pada langkah berikutnya, Anda akan memindahkan gambar dan teks hard code ini untuk dapat menggunakan parameter yang disediakan di composable AlignYourBodyElement agar keduanya dinamis.

Lihat pratinjau composable ini:

pratinjau align your body

Ada beberapa peningkatan yang harus dilakukan. Yang paling kentara, gambar terlalu besar dan tidak berbentuk lingkaran. Anda dapat menyesuaikan composable Image dengan pengubah size dan clip serta parameter contentScale.

Pengubah size menyesuaikan composable agar sesuai dengan ukuran tertentu, mirip dengan pengubah fillMaxWidth dan heightIn yang Anda lihat di langkah sebelumnya. Pengubah clip berfungsi secara berbeda dan mengadaptasi tampilan composable. Anda dapat menetapkannya ke Shape mana pun dan konten klip tersebut akan disusun ke bentuk tersebut.

import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.ui.draw.clip
@Composable
fun AlignYourBodyElement(
   modifier: Modifier = Modifier
) {
   Column(
       modifier = modifier
   ) {
       Image(
           painter = painterResource(R.drawable.ab1_inversions),
           contentDescription = null,
           modifier = Modifier
               .size(88.dp)
               .clip(CircleShape)
       )
       Text(text = stringResource(R.string.ab1_inversions))
   }
}

Saat ini, desain Anda di Pratinjau terlihat seperti ini:

pratinjau align your body

Gambar juga harus diskalakan dengan benar. Untuk melakukannya, kita dapat menggunakan parameter contentScale Image. Ada beberapa opsi, terutama:

pratinjau konten align your body

Dalam hal ini, jenis pemangkasan adalah yang benar untuk digunakan. Setelah menerapkan pengubah dan parameter, kode Anda akan terlihat seperti ini:

import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
@Composable
fun AlignYourBodyElement(
   modifier: Modifier = Modifier
) {
   Column(
       modifier = modifier
   ) {
       Image(
           painter = painterResource(R.drawable.ab1_inversions),
           contentDescription = null,
           contentScale = ContentScale.Crop,
           modifier = Modifier
               .size(88.dp)
               .clip(CircleShape)
       )
       Text( text = stringResource(R.string.ab1_inversions) )
   }
}

Desain Anda sekarang akan terlihat seperti ini:

pratinjau align your body

Sebagai langkah berikutnya, ratakan teks secara horizontal dengan menyetel perataan Column.

Secara umum, untuk meratakan composable di dalam penampung induk, Anda harus menyetel perataan penampung induk tersebut. Jadi, bukannya memberi tahu anak agar memosisikan dirinya sendiri di induknya, Anda memberi tahu induk cara menyelaraskan turunan.

Untuk Column, tentukan bagaimana turunan harus diratakan secara horizontal. Opsinya adalah:

  • Mulai
  • CenterHorizontally
  • Akhir

Untuk Row, Anda menyetel perataan vertikal. Opsinya mirip dengan Column:

  • Atas
  • CenterVertically
  • Bawah

Untuk Box, Anda menggabungkan perataan horizontal dan vertikal. Opsinya adalah:

  • TopStart
  • TopCenter
  • TopEnd
  • CenterStart
  • Center
  • CenterEnd
  • BottomStart
  • BottomCenter
  • BottomEnd

Semua turunan penampung akan mengikuti pola penyelarasan yang sama ini. Anda dapat mengganti perilaku turunan tunggal dengan menambahkan pengubah align ke dalamnya.

Untuk desain ini, teks harus berada di tengah secara horizontal. Untuk melakukannya, setel horizontalAlignment Column ke tengah secara horizontal:

import androidx.compose.ui.Alignment
@Composable
fun AlignYourBodyElement(
   modifier: Modifier = Modifier
) {
   Column(
       horizontalAlignment = Alignment.CenterHorizontally,
       modifier = modifier
   ) {
       Image(
           //..
       )
       Text(
           //..
       )
   }
}

Dengan menerapkan bagian-bagian ini, maka hanya ada beberapa perubahan kecil yang perlu Anda lakukan untuk membuat composable identik dengan desainnya. Coba terapkan kode ini sendiri atau lihat kode akhir jika Anda mengalami kesulitan. Pertimbangkan langkah berikut:

  • Jadikan gambar dan teks dinamis. Teruskan argumen tersebut sebagai argumen ke fungsi composable. Jangan lupa untuk mengupdate Pratinjau yang sesuai dan meneruskan beberapa data hard code.
  • Perbarui teks agar menggunakan gaya tipografi bodyMedium.
  • Perbarui spasi dasar elemen teks per diagram.

garis merah align your body

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

import androidx.compose.foundation.layout.paddingFromBaseline
import androidx.compose.ui.Alignment
import androidx.compose.ui.layout.ContentScale

@Composable
fun AlignYourBodyElement(
   @DrawableRes drawable: Int,
   @StringRes text: Int,
   modifier: Modifier = Modifier
) {
   Column(
       modifier = modifier,
       horizontalAlignment = Alignment.CenterHorizontally
   ) {
       Image(
           painter = painterResource(drawable),
           contentDescription = null,
           contentScale = ContentScale.Crop,
           modifier = Modifier
               .size(88.dp)
               .clip(CircleShape)
       )
       Text(
           text = stringResource(text),
           modifier = Modifier.paddingFromBaseline(top = 24.dp, bottom = 8.dp),
           style = MaterialTheme.typography.bodyMedium
       )
   }
}

@Preview(showBackground = true, backgroundColor = 0xFFF5F0EE)
@Composable
fun AlignYourBodyElementPreview() {
   MySootheTheme {
       AlignYourBodyElement(
           text = R.string.ab1_inversions,
           drawable = R.drawable.ab1_inversions,
           modifier = Modifier.padding(8.dp)
       )
   }
}

Lihat AlignYourBodyElement di tab Design.

pratinjau align your body

6. Kartu Favorite collection - Platform Material

Composable berikutnya yang akan diimplementasikan sama dengan elemen "Align the body". Berikut adalah desainnya, termasuk garis merah:

kartu koleksi favorit

garis merah kartu koleksi favorit

Dalam hal ini, ukuran penuh composable disediakan. Anda dapat melihat bahwa teks harus titleMedium.

Penampung ini menggunakan surfaceVariant sebagai warna latar belakangnya yang berbeda dari latar belakang seluruh layar. Ada juga sudut yang membulat. Kita menentukan ini untuk kartu koleksi favorit menggunakan composable Surface Material.

Anda dapat menyesuaikan Surface sesuai kebutuhan dengan menetapkan parameter dan pengubahnya. Dalam hal ini, permukaan harus memiliki sudut bulat. Anda dapat menggunakan parameter shape untuk ini. Anda akan menggunakan nilai yang berasal dari tema Material, bukan menyetel bentuk ke Shape seperti Gambar di langkah sebelumnya.

Mari kita lihat tampilannya:

import androidx.compose.foundation.layout.Row
import androidx.compose.material3.Surface

@Composable
fun FavoriteCollectionCard(
   modifier: Modifier = Modifier
) {
   Surface(
       shape = MaterialTheme.shapes.medium,
       modifier = modifier
   ) {
       Row {
           Image(
               painter = painterResource(R.drawable.fc2_nature_meditations),
               contentDescription = null
           )
           Text(text = stringResource(R.string.fc2_nature_meditations))
       }
   }
}

Mari kita lihat Pratinjau implementasi ini:

pratinjau koleksi favorit

Selanjutnya, terapkan hal yang dipelajari pada langkah sebelumnya.

  • Tetapkan lebar Row, dan sejajarkan turunannya secara vertikal.
  • Menetapkan ukuran gambar per diagram dan memangkasnya dalam penampungnya.

garis merah koleksi favorit

Coba terapkan perubahan ini sendiri sebelum melihat kode solusi.

Kode Anda sekarang akan terlihat seperti ini:

import androidx.compose.foundation.layout.width

@Composable
fun FavoriteCollectionCard(
   modifier: Modifier = Modifier
) {
   Surface(
       shape = MaterialTheme.shapes.medium,
       modifier = modifier
   ) {
       Row(
           verticalAlignment = Alignment.CenterVertically,
           modifier = Modifier.width(255.dp)
       ) {
           Image(
               painter = painterResource(R.drawable.fc2_nature_meditations),
               contentDescription = null,
               contentScale = ContentScale.Crop,
               modifier = Modifier.size(80.dp)
           )
           Text(
               text = stringResource(R.string.fc2_nature_meditations)
           )
       }
   }
}

Pratinjau sekarang akan terlihat seperti ini:

pratinjau koleksi favorit

Untuk menyelesaikan composable ini, terapkan langkah-langkah berikut:

  • Jadikan gambar dan teks dinamis. Teruskan argumen sebagai argumen ke fungsi composable.
  • Mengubah warna ke surfaceVariant.
  • Perbarui teks agar menggunakan gaya tipografi titleMedium.
  • Perbarui spasi antara gambar dan teks.

Hasil akhir Anda akan terlihat seperti ini:

@Composable
fun FavoriteCollectionCard(
   @DrawableRes drawable: Int,
   @StringRes text: Int,
   modifier: Modifier = Modifier
) {
   Surface(
       shape = MaterialTheme.shapes.medium,
       color = MaterialTheme.colorScheme.surfaceVariant,
       modifier = modifier
   ) {
       Row(
           verticalAlignment = Alignment.CenterVertically,
           modifier = Modifier.width(255.dp)
       ) {
           Image(
               painter = painterResource(drawable),
               contentDescription = null,
               contentScale = ContentScale.Crop,
               modifier = Modifier.size(80.dp)
           )
           Text(
               text = stringResource(text),
               style = MaterialTheme.typography.titleMedium,
               modifier = Modifier.padding(horizontal = 16.dp)
           )
       }
   }
}

//..

@Preview(showBackground = true, backgroundColor = 0xFFF5F0EE)
@Composable
fun FavoriteCollectionCardPreview() {
   MySootheTheme {
       FavoriteCollectionCard(
           text = R.string.fc2_nature_meditations,
           drawable = R.drawable.fc2_nature_meditations,
           modifier = Modifier.padding(8.dp)
       )
   }
}

Lihat Pratinjau FavoriteCollectionCardPreview.

pratinjau koleksi favorit

7. Baris Align your body - Pengaturan

Setelah membuat composable dasar yang ditampilkan di layar, Anda dapat mulai membuat bagian layar yang berbeda.

Mulai dengan baris "Align your body" yang dapat di-scroll.

align your body yang dapat di-scroll

Berikut adalah desain garis merah untuk komponen ini:

garis merah align your body

Ingat bahwa satu blok petak mewakili 8 dp. Jadi, dalam desain ini, ada spasi 16 dp sebelum item pertama, dan setelah item terakhir pada baris. Terdapat spasi 8 dp di antara setiap item.

Di Compose, Anda dapat menerapkan baris yang dapat di-scroll seperti ini menggunakan composable LazyRow. Dokumentasi pada daftar berisi informasi selengkapnya tentang daftar Lambat seperti LazyRow dan LazyColumn. Untuk codelab ini, Anda hanya perlu mengetahui bahwa LazyRow hanya merender elemen yang ditampilkan di layar, bukan semua elemen pada saat yang bersamaan, yang membantu menjaga performa aplikasi Anda.

Mulai dengan implementasi dasar LazyRow ini:

import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items

@Composable
fun AlignYourBodyRow(
   modifier: Modifier = Modifier
) {
   LazyRow(
       modifier = modifier
   ) {
       items(alignYourBodyData) { item ->
           AlignYourBodyElement(item.drawable, item.text)
       }
   }
}

Seperti yang dapat Anda lihat, turunan LazyRow bukan composable. Sebagai gantinya, Anda menggunakan DSL daftar Lambat yang menyediakan metode seperti item dan items yang memunculkan composable sebagai item daftar. Untuk setiap item dalam alignYourBodyData yang diberikan, Anda membuat composable AlignYourBodyElement yang Anda terapkan sebelumnya.

Perhatikan bagaimana hal ini ditampilkan:

pratinjau align your body

Spasi yang kita lihat dalam desain garis merah masih belum ada. Untuk menerapkannya, Anda harus mempelajari pengaturan.

Pada langkah sebelumnya, Anda telah mempelajari penyelarasan, yang digunakan untuk meratakan turunan penampung pada sumbu silang. Untuk Column, sumbu silang adalah sumbu horizontal, sedangkan untuk Row, sumbu silang adalah sumbu vertikal.

Namun, kita juga dapat membuat keputusan tentang cara menempatkan composable turunan pada sumbu utama penampung (horizontal untuk Row, vertikal untuk Column).

Untuk Row, Anda dapat memilih pengaturan berikut:

pengaturan baris

Dan untuk Column:

pengaturan kolom

Selain pengaturan ini, Anda juga dapat menggunakan metode Arrangement.spacedBy() untuk menambahkan spasi tetap di antara setiap composable turunan.

Dalam contoh, metode spacedBy adalah satu-satunya yang perlu Anda gunakan, ketika Anda ingin menempatkan spasi 8 dp di antara setiap item dalam LazyRow.

import androidx.compose.foundation.layout.Arrangement

@Composable
fun AlignYourBodyRow(
   modifier: Modifier = Modifier
) {
   LazyRow(
       horizontalArrangement = Arrangement.spacedBy(8.dp),
       modifier = modifier
   ) {
       items(alignYourBodyData) { item ->
           AlignYourBodyElement(item.drawable, item.text)
       }
   }
}

Sekarang desainnya terlihat seperti ini:

pratinjau align your body

Anda juga perlu menambahkan padding di bagian samping LazyRow. Dalam kasus ini, menambahkan pengubah padding sederhana tidak dapat dilakukan. Coba tambahkan padding ke LazyRow dan lihat bagaimana perilakunya menggunakan pratinjau interaktif:

garis merah align your body

Seperti yang dapat Anda lihat, saat men-scroll, item pertama dan terakhir yang terlihat terpotong di kedua sisi layar.

Untuk mempertahankan padding yang sama, tetapi tetap men-scroll konten dalam batas daftar induk tanpa memotongnya, semua daftar akan memberikan parameter ke LazyRow bernama contentPadding dan menyetelnya ke 16.dp.

import androidx.compose.foundation.layout.PaddingValues

@Composable
fun AlignYourBodyRow(
   modifier: Modifier = Modifier
) {
   LazyRow(
       horizontalArrangement = Arrangement.spacedBy(8.dp),
       contentPadding = PaddingValues(horizontal = 16.dp),
       modifier = modifier
   ) {
       items(alignYourBodyData) { item ->
           AlignYourBodyElement(item.drawable, item.text)
       }
   }
}

Coba pratinjau interaktif untuk melihat perbedaan yang dibuat oleh padding.

align your body yang dapat di-scroll

8. Petak Favorite collections - Petak Lambat

Bagian berikutnya yang akan diterapkan adalah bagian "Koleksi favorit" pada layar. Sebagai ganti satu baris, composable ini membutuhkan petak:

scrolling koleksi favorit

Anda dapat menerapkan bagian ini seperti bagian sebelumnya, dengan membuat LazyRow dan membiarkan setiap item menyimpan Column dengan dua instance FavoriteCollectionCard. Namun, pada langkah ini, Anda akan menggunakan LazyHorizontalGrid, yang memberikan pemetaan yang lebih baik dari item ke elemen petak.

Mulai dengan implementasi petak sederhana dengan dua baris tetap:

import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid
import androidx.compose.foundation.lazy.grid.items

@Composable
fun FavoriteCollectionsGrid(
   modifier: Modifier = Modifier
) {
   LazyHorizontalGrid(
       rows = GridCells.Fixed(2),
       modifier = modifier
   ) {
       items(favoriteCollectionsData) { item ->
           FavoriteCollectionCard(item.drawable, item.text)
       }
   }
}

Seperti yang dapat Anda lihat, Anda cukup mengganti LazyRow dari langkah sebelumnya dengan LazyHorizontalGrid. Namun, langkah ini belum akan memberikan hasil yang benar:

pratinjau koleksi favorit

Petak menempati ruang sebanyak induknya, yang berarti kartu koleksi favorit direntangkan terlalu jauh secara vertikal.

Sesuaikan composable, sehingga

  • Petak memiliki contentPadding horizontal 16 dp.
  • Pengaturan horizontal dan vertikal berjarak 16 dp.
  • Tinggi petak adalah 168 dp.
  • Pengubah FavoriteCollectionCard menentukan tinggi 80 dp.

Kode final akan terlihat seperti ini:

@Composable
fun FavoriteCollectionsGrid(
   modifier: Modifier = Modifier
) {
   LazyHorizontalGrid(
       rows = GridCells.Fixed(2),
       contentPadding = PaddingValues(horizontal = 16.dp),
       horizontalArrangement = Arrangement.spacedBy(16.dp),
       verticalArrangement = Arrangement.spacedBy(16.dp),
       modifier = modifier.height(168.dp)
   ) {
       items(favoriteCollectionsData) { item ->
           FavoriteCollectionCard(item.drawable, item.text, Modifier.height(80.dp))
       }
   }
}

Pratinjau akan terlihat seperti ini:

pratinjau koleksi favorit

9. Bagian beranda - Slot API

Di layar utama MySoothe, ada beberapa bagian yang mengikuti pola yang sama. Masing-masing memiliki judul, dengan beberapa konten yang bervariasi bergantung pada bagian. Berikut adalah desain garis merah yang ingin kita implementasikan:

garis merah bagian beranda

Seperti yang dapat dilihat, setiap bagian memiliki judul dan slot. Judul memiliki beberapa informasi spasi dan gaya yang terkait dengannya. Slot dapat diisi secara dinamis dengan konten yang berbeda, tergantung pada bagian.

Untuk menerapkan penampung bagian fleksibel ini, Anda menggunakan apa yang disebut slot API. Sebelum menerapkan ini, baca bagian di halaman dokumentasi tentang tata letak berbasis slot. Hal ini akan membantu Anda memahami tata letak berbasis slot dan cara menggunakan slot API untuk membuat tata letak semacam itu.

Sesuaikan composable HomeSection untuk menerima judul dan konten slot. Anda juga harus menyesuaikan Pratinjau terkait untuk memanggil HomeSection ini dengan judul dan konten "Align your body":

@Composable
fun HomeSection(
   @StringRes title: Int,
   modifier: Modifier = Modifier,
   content: @Composable () -> Unit
) {
   Column(modifier) {
       Text(stringResource(title))
       content()
   }
}

@Preview(showBackground = true, backgroundColor = 0xFFF5F0EE)
@Composable
fun HomeSectionPreview() {
   MySootheTheme {
       HomeSection(R.string.align_your_body) {
           AlignYourBodyRow()
       }
   }
}

Anda dapat menggunakan parameter content untuk slot composable. Dengan cara ini, saat menggunakan composable HomeSection, Anda dapat menggunakan lambda di akhir untuk mengisi slot konten. Saat composable menyediakan beberapa slot untuk diisi, Anda dapat memberinya nama yang bermakna yang mewakili fungsinya dalam penampung composable yang lebih besar. Misalnya, TopAppBar Material menyediakan slot untuk title, navigationIcon, dan actions.

Mari kita lihat tampilan bagian tersebut dengan implementasi ini:

pratinjau bagian beranda

Composable Text memerlukan beberapa informasi lainnya agar sesuai dengan desain.

garis merah bagian beranda

Perbarui composable Text agar:

  • Menggunakan tipografi titleMedium.
  • Spasi antara dasar teks dan bagian atas adalah 40 dp.
  • Jarak antara dasar dan bagian bawah elemen adalah 16 dp.
  • Padding horizontal adalah 16 dp.

Solusi akhir Anda akan terlihat seperti ini:

@Composable
fun HomeSection(
   @StringRes title: Int,
   modifier: Modifier = Modifier,
   content: @Composable () -> Unit
) {
   Column(modifier) {
       Text(
           text = stringResource(title),
           style = MaterialTheme.typography.titleMedium,
           modifier = Modifier
               .paddingFromBaseline(top = 40.dp, bottom = 16.dp)
               .padding(horizontal = 16.dp)
       )
       content()
   }
}

10. Layar utama - Scroll

Setelah membuat semua elemen penyusun yang terpisah, Anda dapat menggabungkannya ke dalam implementasi layar penuh.

Berikut adalah desain yang Anda coba terapkan:

garis merah bagian beranda

Kami hanya menempatkan kotak penelusuran dan dua bagian di bawah satu sama lain. Ada beberapa spasi yang perlu Anda tambahkan agar semuanya sesuai dengan desain. Satu composable yang belum pernah kita gunakan sebelumnya adalah Spacer, yang membantu kita menempatkan ruang ekstra di dalam Column. Jika akan menyetel padding Column, Anda akan mendapatkan perilaku terpotong yang sama seperti yang kita lihat sebelumnya di petak Favorite Collections.

@Composable
fun HomeScreen(modifier: Modifier = Modifier) {
   Column(modifier) {
       Spacer(Modifier.height(16.dp))
       SearchBar(Modifier.padding(horizontal = 16.dp))
       HomeSection(title = R.string.align_your_body) {
           AlignYourBodyRow()
       }
       HomeSection(title = R.string.favorite_collections) {
           FavoriteCollectionsGrid()
       }
       Spacer(Modifier.height(16.dp))
   }
}

Meskipun desainnya cocok dengan sebagian besar ukuran perangkat, desain harus dapat di-scroll secara vertikal jika perangkat tidak cukup tinggi, misalnya dalam mode lanskap. Hal ini mengharuskan Anda menambahkan perilaku scroll.

Seperti yang kita lihat sebelumnya, tata letak Lazy seperti LazyRow dan LazyHorizontalGrid secara otomatis menambahkan perilaku scroll. Namun, Anda tidak selalu memerlukan tata letak Lambat. Secara umum, Anda akan menggunakan tata letak Lambat jika memiliki banyak elemen dalam daftar atau set data besar untuk dimuat, jadi memunculkan semua item sekaligus akan mengorbankan performa dan akan memperlambat aplikasi Anda. Jika daftar hanya memiliki sejumlah elemen yang terbatas, Anda dapat memilih untuk menggunakan Column atau Row sederhana dan menambahkan perilaku scroll secara manual. Untuk melakukannya, gunakan pengubah verticalScroll atau horizontalScroll. Hal ini memerlukan ScrollState, yang berisi status scroll saat ini, yang digunakan untuk mengubah status scroll dari luar. Dalam hal ini, Anda tidak ingin mengubah status scroll, jadi Anda cukup membuat instance ScrollState persisten menggunakan rememberScrollState.

Hasil akhir Anda akan terlihat seperti ini:

import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll

@Composable
fun HomeScreen(modifier: Modifier = Modifier) {
   Column(
       modifier
           .verticalScroll(rememberScrollState())
   ) {
       Spacer(Modifier.height(16.dp))
       SearchBar(Modifier.padding(horizontal = 16.dp))
       HomeSection(title = R.string.align_your_body) {
           AlignYourBodyRow()
       }
       HomeSection(title = R.string.favorite_collections) {
           FavoriteCollectionsGrid()
       }
       Spacer(Modifier.height(16.dp))
   }
}

Untuk memverifikasi perilaku scroll composable, batasi tinggi Pratinjau dan jalankan dalam pratinjau interaktif:

@Preview(showBackground = true, backgroundColor = 0xFFF5F0EE, heightDp = 180)
@Composable
fun ScreenContentPreview() {
   MySootheTheme { HomeScreen() }
}

scroll konten layar

11. Navigasi bawah - Material

Setelah mengimplementasikan konten layar, Anda siap untuk menambahkan dekorasi jendela. Untuk MySoothe, ada menu navigasi yang memungkinkan pengguna beralih di antara layar yang berbeda.

Pertama, implementasikan composable menu navigasi, lalu sertakan dalam aplikasi Anda.

Mari kita lihat desainnya:

desain navigasi bawah

Untungnya, Anda tidak perlu menerapkan seluruh composable ini sendiri dari awal. Anda dapat menggunakan composable NavigationBar yang merupakan bagian dari library Compose Material. Di dalam composable NavigationBar, Anda dapat menambahkan satu atau beberapa elemen NavigationBarItem, yang kemudian akan diberi gaya secara otomatis oleh library Material.

Mulai dengan implementasi dasar navigasi bawah ini:

import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material.icons.filled.AccountCircle
import androidx.compose.material.icons.filled.Spa

@Composable
private fun SootheBottomNavigation(modifier: Modifier = Modifier) {
   NavigationBar(
       modifier = modifier
   ) {
       NavigationBarItem(
           icon = {
               Icon(
                   imageVector = Icons.Default.Spa,
                   contentDescription = null
               )
           },
           label = {
               Text(
                   text = stringResource(R.string.bottom_navigation_home)
               )
           },
           selected = true,
           onClick = {}
       )
       NavigationBarItem(
           icon = {
               Icon(
                   imageVector = Icons.Default.AccountCircle,
                   contentDescription = null
               )
           },
           label = {
               Text(
                   text = stringResource(R.string.bottom_navigation_profile)
               )
           },
           selected = false,
           onClick = {}
       )
   }
}

Seperti inilah tampilan implementasi dasarnya - tidak banyak kontras antara warna konten dan warna menu navigasi.

pratinjau navigasi bawah

Ada beberapa adaptasi gaya yang harus Anda buat. Pertama-tama, Anda dapat memperbarui warna latar belakang navigasi bawah dengan menetapkan parameter containerColor-nya. Anda dapat menggunakan warna surfaceVariant dari Penetapan Tema Material untuk ini. Solusi akhir Anda akan terlihat seperti ini:

@Composable
private fun SootheBottomNavigation(modifier: Modifier = Modifier) {
   NavigationBar(
       containerColor = MaterialTheme.colorScheme.surfaceVariant,
       modifier = modifier
   ) {
       NavigationBarItem(
           icon = {
               Icon(
                   imageVector = Icons.Default.Spa,
                   contentDescription = null
               )
           },
           label = {
               Text(stringResource(R.string.bottom_navigation_home))
           },
           selected = true,
           onClick = {}
       )
       NavigationBarItem(
           icon = {
               Icon(
                   imageVector = Icons.Default.AccountCircle,
                   contentDescription = null
               )
           },
           label = {
               Text(stringResource(R.string.bottom_navigation_profile))
           },
           selected = false,
           onClick = {}
       )
   }
}

Sekarang menu navigasi akan terlihat seperti ini, perhatikan bagaimana menu tersebut memberikan lebih banyak kontras.

desain navigasi bawah

12. Aplikasi MySoothe - Scaffold

Untuk langkah ini, buat implementasi layar penuh, termasuk navigasi bawah. Gunakan composable Scaffold Material. Scaffold memberi Anda composable tingkat atas yang dapat dikonfigurasi untuk aplikasi yang menerapkan Desain Material. Terdapat slot untuk berbagai konsep Material, salah satunya adalah panel bawah. Di panel bawah ini, Anda dapat menempatkan composable navigasi bawah yang Anda buat di langkah sebelumnya.

Implementasikan composable MySootheAppPortrait(). Ini adalah composable tingkat atas untuk aplikasi Anda, jadi Anda harus:

  • Menerapkan tema Material MySootheTheme.
  • Tambahkan Scaffold.
  • Tetapkan panel bawah menjadi composable SootheBottomNavigation Anda.
  • Setel konten menjadi composable HomeScreen Anda.

Hasil akhir Anda seharusnya:

import androidx.compose.material3.Scaffold

@Composable
fun MySootheAppPortrait() {
   MySootheTheme {
       Scaffold(
           bottomBar = { SootheBottomNavigation() }
       ) { padding ->
           HomeScreen(Modifier.padding(padding))
       }
   }
}

Implementasi Anda kini selesai! Jika ingin memeriksa apakah versi telah diterapkan dengan cara yang sesuai untuk piksel, Anda dapat membandingkan gambar ini dengan implementasi Pratinjau Anda sendiri.

implementasi my soothe

13. Kolom Samping Navigasi - Material

Saat membuat tata letak untuk aplikasi, Anda juga perlu memperhatikan seperti apa tampilannya dalam beberapa konfigurasi, termasuk mode lanskap di ponsel. Berikut adalah desain untuk aplikasi dalam mode lanskap. Perhatikan bagaimana navigasi bawah berubah menjadi kolom samping di sebelah kiri konten layar.

desain lanskap

Untuk menerapkannya, Anda akan menggunakan composable NavigationRail yang merupakan bagian dari library Compose Material dan memiliki implementasi serupa dengan NavigationBar yang digunakan untuk membuat menu navigasi bawah. Di dalam composable NavigationRail, Anda akan menambahkan elemen NavigationRailItem untuk Beranda dan Profil.

desain navigasi bawah

Mari kita mulai dengan implementasi dasar untuk Kolom Samping Navigasi.

import androidx.compose.material3.NavigationRail
import androidx.compose.material3.NavigationRailItem

@Composable
private fun SootheNavigationRail(modifier: Modifier = Modifier) {
   NavigationRail(
   ) {
       Column(
       ) {
           NavigationRailItem(
               icon = {
                   Icon(
                       imageVector = Icons.Default.Spa,
                       contentDescription = null
                   )
               },
               label = {
                   Text(stringResource(R.string.bottom_navigation_home))
               },
               selected = true,
               onClick = {}
           )

           NavigationRailItem(
               icon = {
                   Icon(
                       imageVector = Icons.Default.AccountCircle,
                       contentDescription = null
                   )
               },
               label = {
                   Text(stringResource(R.string.bottom_navigation_profile))
               },
               selected = false,
               onClick = {}
           )
       }
   }
}

pratinjau kolom samping navigasi

Ada beberapa adaptasi gaya yang harus Anda buat.

  • Tambahkan padding 8 dp di awal dan akhir kolom samping.
  • Perbarui warna latar belakang kolom samping navigasi dengan menetapkan parameter containerColor-nya menggunakan warna latar belakang dari Penetapan Tema Material untuk ini. Dengan menetapkan warna latar belakang, warna ikon dan teks akan otomatis disesuaikan dengan warna onBackground tema.
  • Kolom harus mengisi tinggi maksimum.
  • Tetapkan pengaturan vertikal kolom ke tengah.
  • Tetapkan perataan horizontal kolom ke tengah secara horizontal.
  • Tambahkan padding 8 dp di antara dua ikon.

Solusi akhir Anda akan terlihat seperti ini:

import androidx.compose.foundation.layout.fillMaxHeight

@Composable
private fun SootheNavigationRail(modifier: Modifier = Modifier) {
   NavigationRail(
       modifier = modifier.padding(start = 8.dp, end = 8.dp),
       containerColor = MaterialTheme.colorScheme.background,
   ) {
       Column(
           modifier = modifier.fillMaxHeight(),
           verticalArrangement = Arrangement.Center,
           horizontalAlignment = Alignment.CenterHorizontally
       ) {
           NavigationRailItem(
               icon = {
                   Icon(
                       imageVector = Icons.Default.Spa,
                       contentDescription = null
                   )
               },
               label = {
                   Text(stringResource(R.string.bottom_navigation_home))
               },
               selected = true,
               onClick = {}
           )
           Spacer(modifier = Modifier.height(8.dp))
           NavigationRailItem(
               icon = {
                   Icon(
                       imageVector = Icons.Default.AccountCircle,
                       contentDescription = null
                   )
               },
               label = {
                   Text(stringResource(R.string.bottom_navigation_profile))
               },
               selected = false,
               onClick = {}
           )
       }
   }
}

desain kolom samping navigasi

Sekarang, mari kita tambahkan Kolom Samping Navigasi ke tata letak lanskap.

desain lanskap

Untuk versi potret aplikasi, Anda menggunakan Scaffold. Namun, untuk lanskap, Anda akan menggunakan Baris dan menempatkan kolom samping navigasi dan konten layar berdampingan satu sama lain.

@Composable
fun MySootheAppLandscape() {
   MySootheTheme {
       Row {
           SootheNavigationRail()
           HomeScreen()
       }
   }
}

Saat Anda menggunakan Scaffold dalam versi potret, Anda juga harus mengatur warna konten ke latar belakang untuk Anda. Untuk menetapkan warna Kolom Samping Navigasi, gabungkan Baris dalam Platform dan tetapkan ke warna latar belakang.

@Composable
fun MySootheAppLandscape() {
   MySootheTheme {
       Surface(color = MaterialTheme.colorScheme.background) {
           Row {
               SootheNavigationRail()
               HomeScreen()
           }
       }
   }
}

pratinjau lanskap

14. Aplikasi MySoothe - Ukuran jendela

Anda memiliki Pratinjau untuk mode lanskap yang terlihat bagus. Namun, jika Anda menjalankan aplikasi di perangkat atau emulator dan memutarnya di samping, Anda tidak akan melihat versi lanskapnya. Dengan kata lain, kita perlu memberi tahu aplikasi kapan harus menampilkan konfigurasi aplikasi yang sedang digunakan. Untuk melakukannya, gunakan fungsi calculateWindowSizeClass() untuk melihat konfigurasi yang digunakan ponsel.

diagram ukuran jendela

Ada tiga lebar class ukuran jendela: Rapat, Sedang, dan Diperluas. Jika aplikasi dalam mode potret, lebarnya adalah Rapat. Jika aplikasi dalam mode lanskap, lebarnya adalah Diperluas. Untuk tujuan codelab ini, Anda tidak akan menggunakan lebar Sedang.

Di Composable MySootheApp, perbarui ukuran jendela agar dapat menggunakan WindowSizeClass perangkat. Jika rapat, teruskan aplikasi dalam versi potret. Jika menggunakan orientasi lanskap, teruskan aplikasi dalam versi lanskap.

import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
@Composable
fun MySootheApp(windowSize: WindowSizeClass) {
   when (windowSize.widthSizeClass) {
       WindowWidthSizeClass.Compact -> {
           MySootheAppPortrait()
       }
       WindowWidthSizeClass.Expanded -> {
           MySootheAppLandscape()
       }
   }
}

Di setContent(), buat val bernama windowSizeClass yang disetel ke calculateWindowSize() dan teruskan ke MySootheApp().

Karena calculateWindowSize() masih bersifat eksperimental, Anda harus memilih class ExperimentalMaterial3WindowSizeClassApi.

import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass

class MainActivity : ComponentActivity() {
   @OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContent {
           val windowSizeClass = calculateWindowSizeClass(this)
           MySootheApp(windowSizeClass)
       }
   }
}

Sekarang - jalankan aplikasi di emulator atau perangkat Anda dan amati perubahan tampilan saat rotasi.

Versi potret aplikasi

Versi lanskap aplikasi

15. Selamat

Selamat, Anda telah berhasil menyelesaikan codelab ini dan mempelajari tata letak di Compose lebih lanjut. Melalui penerapan desain sebenarnya, Anda telah mempelajari pengubah, perataan, pengaturan, tata letak Lambat, slot API, scroll, komponen Material, dan desain khusus tata letak.

Lihat codelab lain di jalur Compose. Dan lihat contoh kode.

Dokumentasi

Untuk mendapatkan informasi selengkapnya dan panduan tentang topik ini, lihat dokumentasi berikut: