Menambahkan tata letak adaptif ke aplikasi Android berbasis tampilan dengan Compose

1. Sebelum memulai

Perangkat Android hadir dalam berbagai bentuk dan ukuran sehingga Anda perlu membuat tata letak aplikasi yang mengakomodasi berbagai ukuran layar untuk membuatnya tersedia bagi pengguna dan perangkat berbeda dengan satu Paket Android (APK) atau Android App Bundle (AAB). Untuk melakukannya, Anda harus menentukan aplikasi dengan tata letak responsif dan adaptif, bukan menentukannya dengan dimensi statis yang mengasumsikan ukuran dan rasio aspek layar tertentu. Tata letak adaptif berubah berdasarkan ruang layar yang tersedia.

Codelab ini mengajarkan dasar-dasar cara membangun UI adaptif dan menyesuaikan aplikasi yang menampilkan daftar olahraga serta detail setiap olahraga untuk mendukung perangkat layar besar. Aplikasi olahraga terdiri dari tiga layar: utama, favorit, dan setelan. Layar utama menampilkan daftar olahraga dan placeholder untuk berita saat Anda memilih olahraga dari daftar. Layar favorit dan setelan juga menampilkan teks placeholder. Anda memilih item terkait di menu navigasi bawah untuk beralih layar.

Aplikasi dimulai dengan masalah tata letak ini pada layar besar:

  • Anda tidak dapat menggunakannya dalam orientasi potret.
  • Aplikasi menampilkan banyak ruang kosong pada layar besar.
  • Aplikasi selalu menampilkan menu navigasi bawah pada layar besar.

Anda akan membuat aplikasi menjadi adaptif agar aplikasi:

  • Mendukung orientasi lanskap dan potret.
  • Menampilkan daftar olahraga dan berita tentang setiap olahraga secara berdampingan jika ada cukup ruang horizontal untuk melakukannya.
  • Menampilkan komponen navigasi sesuai dengan pedoman Desain Material.

Aplikasi ini adalah aplikasi satu aktivitas dengan beberapa fragmen. Anda menggunakan file berikut:

  • File AndroidManifest.xml, yang memberikan metadata tentang aplikasi olahraga.
  • File MainActivity.kt, yang berisi kode yang dihasilkan dengan file activity_main.xml, anotasi override, class enum yang mewakili ukuran class jendela lebar, dan definisi metode untuk mengambil class ukuran jendela lebar untuk jendela aplikasi. Menu navigasi bawah diinisialisasi saat aktivitas dibuat.
  • File activity_main.xml, yang menentukan tata letak default untuk aktivitas Main.
  • File layout-sw600dp/activity_main.xml, yang menentukan tata letak alternatif untuk aktivitas Main. Tata letak alternatif akan efektif jika lebar jendela aplikasi lebih besar dari atau sama dengan nilai 600dp. Konten sama dengan tata letak default di titik awal.
  • File SportsListFragment.kt, yang berisi implementasi daftar olahraga dan navigasi kembali kustom.
  • File fragment_sports_list.xml, yang menentukan tata letak daftar olahraga.
  • File navigation_menu.xml, yang menentukan item menu navigasi bawah.

Aplikasi olahraga menampilkan daftar olahraga pada jendela yang rapat dengan menu navigasi sebagai komponen navigasi atas. Aplikasi olahraga menampilkan daftar olahraga dan berita olahraga secara berdampingan di jendela berukuran sedang. Kolom samping navigasi muncul sebagai komponen navigasi atas. Aplikasi olahraga menampilkan panel navigasi, daftar olahraga, dan berita di jendela berukuran diperluas.

Gambar 1. Aplikasi olahraga mendukung berbagai ukuran jendela dengan satu APK atau AAB.

Prasyarat

Yang akan Anda pelajari

  • Cara mendukung perubahan konfigurasi.
  • Cara menambahkan tata letak alternatif dengan lebih sedikit modifikasi kode.
  • Cara mengimplementasikan UI detail daftar yang berperilaku berbeda untuk berbagai ukuran jendela.

Yang akan Anda bangun

Aplikasi Android yang mendukung:

  • Orientasi perangkat lanskap
  • Tablet, desktop, dan perangkat seluler
  • Perilaku detail daftar untuk berbagai ukuran layar

Yang akan Anda butuhkan

2. Memulai persiapan

Download kode untuk codelab ini dan siapkan project:

  1. Dari command line, clone kode di repositori GitHub ini:
$ git clone https://github.com/android/add-adaptive-layouts
  1. Di Android Studio, buka project AddingAdaptiveLayout. Project ini dibuat di beberapa cabang git:
  • Cabang main berisi kode awal untuk project ini. Anda membuat perubahan pada cabang ini untuk menyelesaikan codelab.
  • Cabang end berisi solusi untuk codelab ini.

3. Memigrasikan komponen navigasi atas ke Compose

Aplikasi olahraga menggunakan menu navigasi bawah sebagai komponen navigasi atas. Komponen navigasi ini diimplementasikan dengan class BottomNavigationView. Di bagian ini, Anda akan memigrasikan komponen navigasi atas ke Compose.

Menampilkan konten resource menu yang terkait sebagai class tertutup

  1. Buat class MenuItem tertutup untuk menampilkan konten file navigation_menu.xml, lalu teruskan parameter iconId, parameter labelId, dan parameter destinationId.
  2. Tambahkan objek Home, objek Favorite, dan objek Settings sebagai subclass yang sesuai dengan tujuan Anda.
sealed class MenuItem(
    // Resource ID of the icon for the menu item
    @DrawableRes val iconId: Int,
    // Resource ID of the label text for the menu item
    @StringRes val labelId: Int,
    // ID of a destination to navigate users
    @IdRes val destinationId: Int
) {

    object Home: MenuItem(
        R.drawable.ic_baseline_home_24,
        R.string.home,
        R.id.SportsListFragment
    )

    object Favorites: MenuItem(
        R.drawable.ic_baseline_favorite_24,
        R.string.favorites,
        R.id.FavoritesFragment
    )

    object Settings: MenuItem(
        R.drawable.ic_baseline_settings_24,
        R.string.settings,
        R.id.SettingsFragment
    )
}

Mengimplementasikan menu navigasi bawah sebagai fungsi composable

  1. Tentukan fungsi BottomNavigationBar composable yang menggunakan tiga parameter ini: objek menuItems yang disetel ke nilai List<MenuItem>, objek modifier yang disetel ke nilai Modifier = Modifier, dan objek onMenuSelected yang disetel ke fungsi lambda (MenuItem) -> Unit = {}.
  2. Dalam isi fungsi BottomNavigationBar composable, panggil fungsi NavigationBar() yang menggunakan parameter modifier.
  3. Dalam fungsi lambda yang diteruskan ke fungsi NavigationBar(), panggil metode forEach() pada parameter menuItems, lalu panggil fungsi NavigationBarItem() dalam fungsi lambda yang disetel ke panggilan metode foreach().
  4. Teruskan fungsi NavigationBarItem() parameter selected yang disetel ke nilai false; parameter onClick yang disetel ke fungsi lambda yang berisi fungsi onMenuSelected dengan parameter MenuItem; parameter icon yang disetel ke fungsi lambda yang berisi fungsi Icon yang menggunakan parameter painter = painterResource(id = menuItem.iconId) dan parameter contentDescription = null; dan parameter label yang disetel ke fungsi lambda yang berisi fungsi Text yang menggunakan parameter (text = stringResource(id = menuItem.labelId).
@Composable
fun BottomNavigationBar(
    menuItems: List<MenuItem>,
    modifier: Modifier = Modifier,
    onMenuSelected: (MenuItem) -> Unit = {}
) {

    NavigationBar(modifier = modifier) {
        menuItems.forEach { menuItem ->
            NavigationBarItem(
                selected = false,
                onClick = { onMenuSelected(menuItem) },
                icon = {
                    Icon(
                        painter = painterResource(id = menuItem.iconId),
                        contentDescription = null)
                },
                label = { Text(text = stringResource(id = menuItem.labelId))}
            )
        }
    }
}

Mengganti elemen BottomNavigationView dengan elemen ComposeView di file resource tata letak

  • Dalam file activity_main.xml, ganti elemen BottomNavigationView dengan elemen ComposeView. Tindakan ini akan menyematkan komponen navigasi bawah ke tata letak UI berbasis tampilan dengan Compose.

activity_main.xml

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/nav_host_fragment_content_main"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:defaultNavHost="true"
            app:layout_constraintBottom_toTopOf="@id/top_navigation"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:navGraph="@navigation/nav_graph" />

        <androidx.compose.ui.platform.ComposeView
            android:id="@+id/navigation"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:menu="@menu/top_navigation" />
    </androidx.constraintlayout.widget.ConstraintLayout>

Mengintegrasikan menu navigasi bawah berbasis Compose dengan tata letak UI berbasis tampilan

  1. Di file MainActivity.kt, tentukan variabel navigationMenuItems yang ditetapkan ke daftar objek MenuItem. Objek MenuItems muncul di menu navigasi bawah dalam urutan daftar.
  2. Panggil fungsi BottomNavigationBar() untuk menyematkan menu navigasi bawah di objek ComposeView.
  3. Buka tujuan yang terkait dengan item yang dipilih oleh pengguna dalam fungsi callback yang diteruskan ke fungsi BottomNavigationBar.

MainActivity.kt

val navigationMenuItems = listOf(
    MenuItem.Home,
    MenuItem.Favorites,
    MenuItem.Settings
)

binding.navigation.setContent {
    MaterialTheme {
        BottomNavigationBar(menuItems = navigationMenuItems){ menuItem ->
            navController.navigate(screen.destinationId)
        }
    }
}

4. Mendukung orientasi horizontal

Jika aplikasi Anda mendukung perangkat layar besar, aplikasi tersebut diharapkan dapat mendukung orientasi lanskap dan orientasi potret. Saat ini, aplikasi Anda hanya memiliki satu aktivitas: aktivitas MainActivity.

Orientasi tampilan aktivitas pada perangkat ditetapkan di file AndroidManifest.xml dengan atribut android:screenOrientation, yang ditetapkan ke nilai portrait.

Buat aplikasi Anda mendukung orientasi lanskap:

  1. Tetapkan atribut android:screenOrientation ke nilai fullUser. Dengan konfigurasi ini, pengguna dapat mengunci orientasi layarnya. Orientasi ditentukan berdasarkan sensor orientasi perangkat untuk setiap empat orientasi.

AndroidManifest.xml

<activity
    android:name=".MainActivity"
    android:exported="true"
    android:screenOrientation="fullUser">

Aplikasi olahraga mendukung orientasi horizontal dengan menetapkan nilai fullUser ke atribut android:screenOrientation dari elemen aktivitas dalam file AndroidManifest.xml.

Gambar 2. Aplikasi berjalan dalam orientasi horizontal setelah Anda memperbarui file AndroidManifest.xml.

5. Class ukuran jendela

Ini adalah nilai titik henti sementara yang membantu mengklasifikasikan ukuran jendela ke dalam class ukuran yang telah ditentukan sebelumnya—rapat, sedang, dan diperluas—dengan ukuran jendela mentah yang tersedia untuk aplikasi Anda. Anda akan menggunakan class ukuran ini saat mendesain, mengembangkan, dan menguji tata letak adaptif.

Lebar dan tinggi yang tersedia dipartisi satu per satu sehingga aplikasi Anda selalu dikaitkan dengan dua class ukuran jendela: class ukuran jendela lebar dan class ukuran jendela tinggi.

Ada dua titik henti sementara di antara tiga class ukuran jendela lebar. Nilai 600 dp adalah titik henti sementara antara rapat dan sedang, dan nilai 840 dp adalah nilai antara class ukuran jendela lebar sedang dan diperluas.

Gambar 3. Class ukuran jendela lebar dan titik henti sementara yang terkait.

Ada dua titik henti sementara untuk tiga class ukuran jendela tinggi. Nilai 480 dp adalah nilai antara class ukuran jendela tinggi rapat dan sedang, dan nilai 900 dp adalah nilai antara class ukuran jendela tinggi sedang dan diperluas.

Gambar 4. Class ukuran jendela tinggi dan titik henti sementara yang terkait.

Class ukuran jendela mewakili ukuran jendela saat ini dari aplikasi Anda. Dengan kata lain, Anda tidak dapat menentukan class ukuran jendela berdasarkan ukuran perangkat fisik. Meskipun aplikasi Anda berjalan di perangkat yang sama, class ukuran jendela terkait akan berubah berdasarkan konfigurasi, seperti saat Anda menjalankan aplikasi dalam mode layar terpisah. Hal ini memiliki dua konsekuensi penting:

  • Perangkat fisik tidak menjamin class ukuran jendela tertentu.
  • Class ukuran jendela dapat berubah sepanjang masa penggunaan aplikasi Anda.

Setelah menambahkan tata letak adaptif ke aplikasi, Anda akan menguji aplikasi di semua rentang ukuran jendela, terutama pada class ukuran jendela rapat, sedang, dan diperluas. Pengujian untuk setiap class ukuran jendela diperlukan, tetapi tidak memadai dalam banyak kasus. Penting untuk menguji aplikasi pada berbagai ukuran jendela guna memastikan bahwa UI diskalakan dengan benar. Untuk mengetahui informasi selengkapnya, lihat Tata letak layar besar dan Kualitas aplikasi layar besar.

6. Menata letak panel daftar dan detail secara berdampingan di layar besar

UI detail daftar mungkin perlu berperilaku berbeda sesuai dengan class ukuran jendela lebar saat ini. Jika class ukuran jendela lebar sedang atau diperluas dikaitkan dengan aplikasi Anda, itu berarti aplikasi tersebut dapat memiliki cukup ruang untuk menampilkan panel daftar dan panel detail secara berdampingan, sehingga pengguna dapat melihat daftar item dan detail item yang dipilih tanpa transisi layar. Namun, panel ini bisa menjadi terlalu padat pada layar yang lebih kecil, yang akan lebih baik jika menampilkan panel satu per satu dengan panel daftar ditampilkan di awal. Panel detail menampilkan detail item yang dipilih saat pengguna mengetuk item dalam daftar. Class SlidingPaneLayout mengelola logika untuk menentukan mana dari dua pengalaman pengguna ini yang sesuai dengan ukuran jendela saat ini.

Mengonfigurasi tata letak panel daftar

Class SlidingPaneLayout adalah komponen UI berbasis tampilan. Anda akan mengubah file resource tata letak untuk panel daftar, yang merupakan file fragment_sports_list.xml dalam codelab ini.

Class SlidingPaneLayout menggunakan dua elemen turunan. Atribut lebar dan berat setiap elemen turunan adalah faktor utama class SlidingPaneLayout untuk menentukan apakah jendela cukup besar untuk menampilkan dua tampilan secara berdampingan. Jika tidak, daftar layar penuh akan diganti dengan UI detail layar penuh. Nilai berat merujuk pada ukuran dua panel secara proporsional jika ukuran jendela lebih besar dari persyaratan minimum untuk menampilkan panel secara berdampingan.

Class SlidingPaneLayout telah diterapkan ke file fragment_sports_list.xml. Panel daftar dikonfigurasi agar memiliki lebar 1280dp. Inilah alasan panel daftar dan detail tidak muncul secara berdampingan.

Buat panel ditampilkan secara berdampingan saat layar lebih besar dari lebar 580dp:

  • Tetapkan RecyclerView ke lebar 280dp.

fragment_sports_list.xml

<androidx.slidingpanelayout.widget.SlidingPaneLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/sliding_pane_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SportsListFragment">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="280dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:clipToPadding="false"
        android:padding="8dp"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

    <androidx.fragment.app.FragmentContainerView
        android:layout_height="match_parent"
        android:layout_width="300dp"
        android:layout_weight="1"
        android:id="@+id/detail_container"
        android:name="com.example.android.sports.NewsDetailsFragment"/>
</androidx.slidingpanelayout.widget.SlidingPaneLayout>

Setelah Anda memperbarui file sports_list_fragment.xml, aplikasi olahraga akan menampilkan daftar olahraga dan berita untuk olahraga yang dipilih secara berdampingan.

Gambar 5. Panel daftar dan detail muncul berdampingan setelah Anda memperbarui file resource tata letak.

Menukar panel detail

Sekarang panel daftar dan detail muncul berdampingan ketika class ukuran jendela lebar sedang atau diperluas dikaitkan dengan aplikasi Anda. Namun, layar sepenuhnya bertransisi ke panel detail terjadi ketika pengguna memilih item dari panel daftar.

Aplikasi melakukan transisi layar dan hanya menampilkan berita olahraga, sementara aplikasi diharapkan terus menampilkan daftar olahraga dan berita secara berdampingan.

Gambar 6. Layar bertransisi ke panel detail setelah Anda memilih olahraga dari daftar.

Masalah ini disebabkan oleh navigasi yang dipicu saat pengguna memilih item dari panel daftar. Kode yang relevan tersedia di file SportsListFragment.kt.

SportsListFragment.kt

val adapter = SportsAdapter {
    sportsViewModel.updateCurrentSport(it)
    // Navigate to the details pane.
    val action =
       SportsListFragmentDirections.actionSportsListFragmentToNewsFragment()
    this.findNavController().navigate(action)
}

Pastikan layar hanya sepenuhnya bertransisi ke panel detail saat tidak ada cukup ruang untuk menampilkan panel daftar dan detail secara berdampingan:

  • Dalam variabel fungsi adapter, tambahkan pernyataan if yang memeriksa apakah atribut isSlidable dari class SlidingPaneLayout bernilai benar dan atribut isOpen dari class SlidingPaneLayout bernilai salah.

SportsListFragment.kt

val adapter = SportsAdapter {
    sportsViewModel.updateCurrentSport(it)
    if(slidingPaneLayout.isSlidable && !slidingPaneLayout.isOpen){
        // Navigate to the details pane.
        val action =
           SportsListFragmentDirections.actionSportsListFragmentToNewsFragment()
        this.findNavController().navigate(action)
    }
}

7. Memilih komponen navigasi yang tepat berdasarkan class ukuran jendela lebar

Desain Material mengharapkan aplikasi Anda memilih komponen secara adaptif. Di bagian ini, Anda memilih komponen navigasi untuk menu navigasi atas berdasarkan class ukuran jendela lebar saat ini. Tabel ini menjelaskan komponen navigasi yang diharapkan untuk setiap class ukuran jendela:

Class ukuran jendela lebar

Komponen navigasi

Rapat

Navigasi bawah

Sedang

Kolom samping navigasi

Diperluas

Panel navigasi permanen

Mengimplementasikan kolom samping navigasi

  1. Buat fungsi NavRail() composable yang menggunakan tiga parameter: objek menuItems yang disetel ke nilai List<MenuItem>, objek modifier yang disetel ke nilai Modifier, dan fungsi lambda onMenuSelected.
  2. Dalam isi fungsi, panggil fungsi NavigationRail() yang menggunakan objek modifier sebagai parameter.
  3. Panggil fungsi NavigationRailItem() untuk setiap objek MenuItem di objek menuItems seperti yang Anda lakukan dengan fungsi NavigationBarItem di fungsi BottomNavigationBar().

Mengimplementasikan panel navigasi permanen

  1. Buat fungsi NavigationDrawer() composable yang menggunakan tiga parameter ini: objek menuItems yang disetel ke nilai List<MenuItem>, objek modifier yang disetel ke nilai Modifier, dan fungsi lambda onMenuSelected.
  2. Dalam isi fungsi, panggil fungsi Column() yang menggunakan objek modifier sebagai parameter.
  3. Panggil fungsi Row() untuk setiap objek MenuItem pada objek menuItems.
  4. Dalam isi fungsi Row(), tambahkan label icon dan text seperti yang Anda lakukan pada fungsi NavigationBarItem di fungsi BottomNavigationBar().

Memilih komponen navigasi yang tepat berdasarkan class ukuran jendela lebar

  1. Untuk mengambil class ukuran jendela lebar saat ini, panggil fungsi rememberWidthSizeClass() di dalam fungsi composable yang diteruskan ke metode setContent() pada objek ComposeView.
  2. Buat cabang bersyarat untuk memilih komponen navigasi berdasarkan class ukuran jendela lebar yang diambil, lalu panggil komponen yang dipilih.
  3. Teruskan objek Modifier ke fungsi NavigationDrawer untuk menentukan lebarnya sebagai nilai 256dp.

ActivityMain.kt

binding.navigation.setContent {
    MaterialTheme {
        when(rememberWidthSizeClass()){
            WidthSizeClass.COMPACT ->
                BottomNavigationBar(menuItems = navigationMenuItems){ menuItem ->
                    navController.navigate(screen.destinationId)
                }
            WidthSizeClass.MEDIUM ->
                NavRail(menuItems = navigationMenuItems){ menuItem ->
                    navController.navigate(screen.destinationId)
                }
            WidthSizeClass.EXPANDED ->
                NavigationDrawer(
                    menuItems = navigationMenuItems,
                    modifier = Modifier.width(256.dp)
                ) { menuItem ->
                    navController.navigate(screen.destinationId)
                }
        }

    }
}

Menempatkan komponen navigasi di posisi yang tepat

Sekarang aplikasi Anda dapat memilih komponen navigasi yang tepat berdasarkan class ukuran jendela lebar saat ini, tetapi komponen yang dipilih tidak dapat ditempatkan seperti yang Anda harapkan. Hal ini karena elemen ComposeView ditempatkan di bawah elemen FragmentViewContainer.

Update resource tata letak alternatif untuk class MainActivity:

  1. Buka file layout-sw600dp/activity_main.xml.
  2. Perbarui batasan untuk menata letak elemen ComposeView dan elemen FragmentContainer secara horizontal.

layout-sw600dp/activity_main.xml

  <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/nav_host_fragment_content_main"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:defaultNavHost="true"
            app:layout_constraintLeft_toRightOf="@+id/top_navigation"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:navGraph="@navigation/nav_graph" />

        <androidx.compose.ui.platform.ComposeView
            android:id="@+id/top_navigation"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:menu="@menu/top_navigation" />
    </androidx.constraintlayout.widget.ConstraintLayout>

Setelah modifikasi, aplikasi memilih komponen navigasi yang tepat berdasarkan class ukuran jendela lebar yang terkait. Screenshot pertama menampilkan layar untuk class ukuran jendela lebar sedang. Screenshot kedua menampilkan layar untuk class ukuran jendela lebar yang diluaskan.

Aplikasi olahraga menampilkan kolom samping navigasi, daftar olahraga, dan berita saat dikaitkan dengan class ukuran jendela lebar sedang. Aplikasi olahraga menampilkan panel navigasi, daftar olahraga, dan berita di layar utama saat aplikasi dikaitkan dengan class ukuran jendela lebar yang diluaskan.

Gambar 7. Layar untuk class ukuran jendela lebar sedang dan diluaskan.

8. Selamat

Selamat! Anda telah menyelesaikan codelab ini dan mempelajari cara menambahkan tata letak adaptif ke aplikasi Android berbasis Tampilan dengan Compose. Dengan demikian, Anda telah mempelajari class SlidingPaneLayout, class ukuran jendela, dan pemilihan komponen navigasi berdasarkan class ukuran jendela lebar.

Pelajari lebih lanjut