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 paneli 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 Components w ramach typowych wzorów i interakcji ekranowych. Na tej stronie opisaliśmy, jak przenieść implementację CoordinatorLayout, aby używać jej w Compose.Scaffold

Etapy migracji

Aby przenieść usługę 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 następnie dodaj element ComposeView, aby go zastąpić.

    <!--  <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 swoim fragmencie lub aktywności znajdź odwołanie do dodanego przed chwilą ComposeView i wywołaj przy nim 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. Ponieważ główna treść w powyższym pliku XML to ViewPager2, użyjemy zmiennej HorizontalPager, która jest jego odpowiednikiem w usłudze Compose. Lambda content w komponencie Scaffold otrzymuje też instancję PaddingValues, która powinna zostać zastosowana do katalogu głównego treści. Aby zastosować PaddingValues do HorizontalPager, możesz użyć polecenia Modifier.padding.

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

Częste 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 pliku Nested scroll sample na stronie AOSP.

Szuflady

Dzięki widokom możesz wdrożyć panel nawigacji, używając DrawerLayout jako widoku głównego. Z kolei CoordinatorLayout jest widokiem podrzędnym DrawerLayout. Element DrawerLayout zawiera też inny widok podrzędny, np. NavigationView, w którym wyświetlane są opcje nawigacji w szufladzie.

W Compose możesz zaimplementować panel nawigacyjny 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 Suflady.

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 artykule o snackbarach.

Więcej informacji

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