Przenieś układ koordynatora do tworzenia wiadomości

CoordinatorLayout to ViewGroup, który umożliwia tworzenie złożonych, nakładających się i zagnieżdżonych układów. Jest on używany jako kontener, który umożliwia określone interakcje w ramach Materiałowego Designu, takie jak rozwijanie i zwijanie pasków narzędzi i elementów dolnych w widokach.

W sekcji Tworzenie najbliższym odpowiednikiem elementu CoordinatorLayout jest element Scaffold. Scaffold udostępnia gniazda treści do łączenia komponentów Material Design w ramach typowych wzorów i interakcji ekranowych. Na tej stronie opisaliśmy, jak przenieść implementację CoordinatorLayout, aby używać Scaffold w Compose.

Etapy migracji

Aby przenieść CoordinatorLayout do Scaffold, wykonaj te czynności:

  1. W tym fragmencie CoordinatorLayout zawiera AppBarLayout, który zawiera ToolBar, ViewPagerFloatingActionButton. Skomentuj element CoordinatorLayout i jego podrzędne z hierarchii interfejsu użytkownika, a na ich miejsce dodaj element ComposeView.

    <!--  <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. W fragmentie lub aktywności uzyskaj odwołanie do dodanego właśnie elementu ComposeView i wywołaj metodę setContent. W ciele metody ustaw jako jej zawartość zmienną Scaffold:

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

  3. W treściach Scaffold dodaj główne treści ekranu. Główna treść w pliku XML powyżej to element ViewPager2, więc użyjemy elementu HorizontalPager, który jest jego odpowiednikiem w komponencie. Lambda content w komponencie Scaffold otrzymuje też instancję PaddingValues, która powinna zostać zastosowana do katalogu głównego treści. Możesz użyć Modifier.padding, aby zastosować tę samą wartość PaddingValues do HorizontalPager.

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

  4. Użyj innych sekcji treści, które udostępnia Scaffold, aby dodać więcej elementów ekranu i przenieść pozostałe widoki podrzędne. Możesz użyć pola topBar, aby dodać TopAppBar, a pola floatingActionButton, aby podać 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 */ }
        }
    }

Typowe zastosowania

Zwijanie i rozwijanie pasków narzędzi

Aby zwinąć lub rozwinąć pasek narzędzi za pomocą CoordinatorLayout, w systemie widoku użyj elementu AppBarLayout jako kontenera dla paska narzędzi. Następnie możesz określić Behavior za pomocą elementu layout_behavior w kodzie XML w powiązanym widoku przewijania (np. RecyclerView lub NestedScrollView), aby określić, jak pasek narzędzi ma się składać/rozwijać podczas przewijania.

W sekcji „Tworzenie” możesz uzyskać podobny efekt, używając TopAppBarScrollBehavior. Aby na przykład wdrożyć pasek narzędzi, który można zwinąć lub rozwinąć, tak aby był widoczny po przewinięciu w górę, wykonaj te czynności:

  1. Aby utworzyć dokument TopAppBarScrollBehavior, zadzwoń na numer TopAppBarDefaults.enterAlwaysScrollBehavior().
  2. Prześlij utworzony TopAppBarScrollBehavior do TopAppBar.
  3. Połącz NestedScrollConnectionModifier.nestedScrollScaffold, aby Scaffold mógł otrzymywać zdarzenia przewijania zagnieżdżonego podczas przewijania treści do góry lub w dół. Dzięki temu pasek aplikacji może się odpowiednio składać i rozkładać podczas przewijania treści.

    // 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 */
        // ...
    }

Dostosowywanie efektu zwijania/rozwijania

Aby dostosować efekt animacji zwijania/rozwijania, możesz podać kilka parametrów enterAlwaysScrollBehavior. TopAppBarDefaults udostępnia też inne TopAppBarScrollBehavior, takie jak exitUntilCollapsedScrollBehavior, które rozwija pasek aplikacji tylko wtedy, gdy przewiniesz treści do końca.

Aby utworzyć całkowicie niestandardowy efekt (np. efekt paralaksy), możesz też utworzyć własną NestedScrollConnection i ręcznie przesuwać pasek narzędzi podczas przewijania treści. Przykładowy kod znajdziesz w przykładie zagnieżdżonego przewijania na stronie AOSP.

Szuflady

W przypadku widoków schowanka nawigacyjna jest implementowana za pomocą widoku wyższego poziomu DrawerLayout. Z kolei CoordinatorLayout jest widokiem podrzędnym DrawerLayout. Element DrawerLayout zawiera też inny widok podrzędny, np. NavigationView, aby wyświetlić opcje nawigacji w schowku.

W komponencie tworzenia możesz zaimplementować szufladę nawigacyjną za pomocą komponentu ModalNavigationDrawer. ModalNavigationDrawer oferuje drawerContent miejsce na szufladę i content miejsce na zawartość ekranu.

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

Więcej informacji znajdziesz w sekcji Drawers.

Paski powiadomień

Scaffold udostępnia slot snackbarHost, który może przyjmować komponent SnackbarHost, aby wyświetlić element 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
    // ...
}

Więcej informacji znajdziesz w sekcji Snackbars.

Więcej informacji

Więcej informacji o przenoszeniu CoordinatorLayout do Compose znajdziesz w tych materiałach: