Memigrasikan CoordinatorLayout ke Compose

CoordinatorLayout adalah ViewGroup yang memungkinkan aktivitas kompleks, tumpang-tindih, dan {i>nested layout<i} (tata letak bertingkat). Ini digunakan sebagai kontainer untuk memungkinkan Desain Material tertentu interaksi, seperti toolbar memperluas/menciutkan dan sheet bawah, untuk Tampilan yang ada di dalamnya.

Di Compose, padanan terdekat dari CoordinatorLayout adalah Scaffold. Scaffold menyediakan slot konten untuk menggabungkan Material Komponen ke dalam pola layar dan interaksi umum. Halaman ini menjelaskan cara Anda dapat memigrasikan penerapan CoordinatorLayout untuk menggunakan Scaffold di Tulis.

Langkah migrasi

Untuk memigrasikan CoordinatorLayout ke Scaffold, ikuti langkah-langkah berikut:

  1. Dalam cuplikan di bawah, CoordinatorLayout berisi AppBarLayout untuk yang berisi ToolBar, ViewPager, dan FloatingActionButton. Beri Komentar CoordinatorLayout dan turunannya dari hierarki UI dan menambahkan elemen ComposeView untuk menggantinya.

    <!--  <androidx.coordinatorlayout.widget.CoordinatorLayout-->
    <!--      android:id="@+id/coordinator_layout"-->
    <!--      android:layout_width="match_parent"-->
    <!--      android:layout_height="match_parent"-->
    <!--      android:fitsSystemWindows="true">-->
    
    <!--    <androidx.compose.ui.platform.ComposeView-->
    <!--        android:id="@+id/compose_view"-->
    <!--        android:layout_width="match_parent"-->
    <!--        android:layout_height="match_parent"-->
    <!--        app:layout_behavior="@string/appbar_scrolling_view_behavior" />-->
    
    <!--    <com.google.android.material.appbar.AppBarLayout-->
    <!--        android:id="@+id/app_bar_layout"-->
    <!--        android:layout_width="match_parent"-->
    <!--        android:layout_height="wrap_content"-->
    <!--        android:fitsSystemWindows="true"-->
    <!--        android:theme="@style/Theme.Sunflower.AppBarOverlay">-->
    
        <!-- AppBarLayout contents here -->
    
    <!--    </com.google.android.material.appbar.AppBarLayout>-->
    
    <!--  </androidx.coordinatorlayout.widget.CoordinatorLayout>-->
    
    <androidx.compose.ui.platform.ComposeView
        android:id="@+id/compose_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    
  2. Di Fragment atau Activity Anda, dapatkan referensi ke ComposeView yang Anda baru saja ditambahkan dan memanggil metode setContent di dalamnya. Dalam isi metode, menetapkan Scaffold sebagai kontennya:

    composeView.setContent {
        Scaffold(Modifier.fillMaxSize()) { contentPadding ->
            // Scaffold contents
            // ...
        }
    }

  3. Di konten Scaffold, tambahkan konten utama layar dalam anotasi. Karena konten utama dalam XML di atas adalah ViewPager2, kita akan menggunakan HorizontalPager, yang setara dengan Compose. Lambda content dari Scaffold juga menerima instance PaddingValues yang seharusnya diterapkan ke root konten. Anda dapat menggunakan Modifier.padding untuk menerapkan PaddingValues ke HorizontalPager.

    composeView.setContent {
        Scaffold(Modifier.fillMaxSize()) { contentPadding ->
            val pagerState = rememberPagerState {
                10
            }
            HorizontalPager(
                state = pagerState,
                modifier = Modifier.padding(contentPadding)
            ) { /* Page contents */ }
        }
    }

  4. Gunakan slot konten lain yang disediakan Scaffold untuk menambahkan lebih banyak elemen layar dan memigrasikan View turunan yang tersisa. Anda dapat menggunakan slot topBar untuk menambahkan TopAppBar, dan slot floatingActionButton untuk memberikan FloatingActionButton

    composeView.setContent {
        Scaffold(
            Modifier.fillMaxSize(),
            topBar = {
                TopAppBar(
                    title = {
                        Text("My App")
                    }
                )
            },
            floatingActionButton = {
                FloatingActionButton(
                    onClick = { /* Handle click */ }
                ) {
                    Icon(
                        Icons.Filled.Add,
                        contentDescription = "Add Button"
                    )
                }
            }
        ) { contentPadding ->
            val pagerState = rememberPagerState {
                10
            }
            HorizontalPager(
                state = pagerState,
                modifier = Modifier.padding(contentPadding)
            ) { /* Page contents */ }
        }
    }

Kasus penggunaan umum

Menciutkan dan meluaskan toolbar

Di sistem View, untuk menciutkan dan meluaskan toolbar dengan CoordinatorLayout, Anda menggunakan AppBarLayout sebagai penampung untuk toolbar. Anda kemudian dapat menentukan Behavior hingga layout_behavior dalam XML pada elemen terkait yang dapat di-scroll Tampilan (seperti RecyclerView atau NestedScrollView) untuk mendeklarasikan cara toolbar menciutkan/memperluas saat Anda men-scroll.

Di Compose, Anda dapat mencapai efek serupa melalui TopAppBarScrollBehavior Misalnya, untuk menerapkan fungsi menciutkan/memperluas agar bilah alat muncul saat Anda menggulir ke atas, ikuti langkah-langkah berikut:

  1. Panggil TopAppBarDefaults.enterAlwaysScrollBehavior() untuk membuat TopAppBarScrollBehavior.
  2. Berikan TopAppBarScrollBehavior yang dibuat ke TopAppBar.
  3. Hubungkan NestedScrollConnection melalui Modifier.nestedScroll di Scaffold sehingga Scaffold dapat menerima peristiwa scroll bertingkat sebagai konten yang dapat di-scroll akan di-scroll ke atas/bawah. Dengan cara ini, panel aplikasi yang dimuat bisa menciutkan/meluaskan dengan tepat saat konten di-scroll.

    // 1. Create the TopAppBarScrollBehavior
    val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
    
    Scaffold(
        topBar = {
            TopAppBar(
                title = {
                    Text("My App")
                },
                // 2. Provide scrollBehavior to TopAppBar
                scrollBehavior = scrollBehavior
            )
        },
        // 3. Connect the scrollBehavior.nestedScrollConnection to the Scaffold
        modifier = Modifier
            .fillMaxSize()
            .nestedScroll(scrollBehavior.nestedScrollConnection)
    ) { contentPadding ->
        /* Contents */
        // ...
    }

Menyesuaikan efek scroll menciutkan/memperluas

Anda dapat menyediakan beberapa parameter untuk enterAlwaysScrollBehavior untuk menyesuaikan efek animasi menciutkan/memperluas. TopAppBarDefaults juga menyediakan TopAppBarScrollBehavior lain seperti exitUntilCollapsedScrollBehavior, yang hanya memperluas panel aplikasi saat konten akan di-scroll ke bawah.

Untuk membuat efek yang sepenuhnya kustom (misalnya, efek paralaks), Anda dapat buat juga NestedScrollConnection Anda sendiri dan offset toolbar secara manual sebagai konten akan bergulir. Lihat Contoh scroll bertingkat di AOSP untuk mengetahui contoh kode.

Panel samping

Dengan View, Anda menerapkan panel navigasi menggunakan elemen DrawerLayout sebagai tampilan root. Selanjutnya, CoordinatorLayout Anda adalah tampilan turunan DrawerLayout. DrawerLayout juga berisi turunan lain , seperti NavigationView, untuk menampilkan opsi navigasi di panel samping.

Di Compose, Anda dapat mengimplementasikan panel navigasi menggunakan Composable ModalNavigationDrawer. ModalNavigationDrawer menawarkan Slot drawerContent untuk panel samping dan slot content untuk panel saat ini.

ModalNavigationDrawer(
    drawerContent = {
        ModalDrawerSheet {
            Text("Drawer title", modifier = Modifier.padding(16.dp))
            Divider()
            NavigationDrawerItem(
                label = { Text(text = "Drawer Item") },
                selected = false,
                onClick = { /*TODO*/ }
            )
            // ...other drawer items
        }
    }
) {
    Scaffold(Modifier.fillMaxSize()) { contentPadding ->
        // Scaffold content
        // ...
    }
}

Lihat Panel Samping untuk mempelajari lebih lanjut.

Snackbar

Scaffold menyediakan slot snackbarHost, yang dapat menerima SnackbarHost composable untuk menampilkan Snackbar.

val scope = rememberCoroutineScope()
val snackbarHostState = remember { SnackbarHostState() }
Scaffold(
    snackbarHost = {
        SnackbarHost(hostState = snackbarHostState)
    },
    floatingActionButton = {
        ExtendedFloatingActionButton(
            text = { Text("Show snackbar") },
            icon = { Icon(Icons.Filled.Image, contentDescription = "") },
            onClick = {
                scope.launch {
                    snackbarHostState.showSnackbar("Snackbar")
                }
            }
        )
    }
) { contentPadding ->
    // Screen content
    // ...
}

Lihat Snackbars untuk mempelajari lebih lanjut.

Pelajari lebih lanjut

Untuk informasi selengkapnya tentang memigrasikan CoordinatorLayout ke Compose, lihat dokumentasi referensi berikut: