Przenieś układ koordynatora do tworzenia wiadomości

CoordinatorLayout to element typu ViewGroup, który umożliwia obsługę złożonych, nakładających się i zagnieżdżonych układów. Służy jako kontener do obsługi określonych interakcji Material Design, np. rozwijania i zwijania pasków narzędzi oraz arkuszy u dołu, w widokach, które się w nim znajdują.

W funkcji Compose najbliższy odpowiednik klasy CoordinatorLayout to Scaffold. Scaffold udostępnia przedziały na treści, które pozwalają łączyć komponenty Material Design w typowe wzorce ekranu i interakcje. Na tej stronie opisujemy, jak przeprowadzić migrację implementacji CoordinatorLayout, aby umożliwić korzystanie z Scaffold w tworzeniu wiadomości.

Etapy migracji

Aby przenieść usługę CoordinatorLayout do Scaffold, wykonaj te czynności:

  1. We fragmencie kodu poniżej fragment CoordinatorLayout zawiera element AppBarLayout obejmujący ToolBar, ViewPager i FloatingActionButton. Skomentuj obiekt CoordinatorLayout i jego elementy 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 treści metody ustaw Scaffold jako jej zawartość:

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

  3. W treści urządzenia Scaffold dodaj główne treści z ekranu. Ponieważ główna treść w powyższym kodzie XML to ViewPager2, użyjemy zmiennej HorizontalPager, która jest jego odpowiednikiem w usłudze Compose. Funkcja lambda content funkcji Scaffold otrzymuje też instancję PaddingValues, którą należy zastosować 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 boksów na treści dostępnych w usłudze Scaffold, aby dodać więcej elementów ekranu i przenieść pozostałe widoki podrzędne. Możesz użyć przedziału topBar, by dodać TopAppBar, a floatingActionButton, by udostępnić 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 w systemie widoku zwinąć i rozwinąć pasek narzędzi za pomocą elementu CoordinatorLayout, jako kontenera paska narzędzi musisz użyć elementu AppBarLayout. Następnie możesz określić w formacie XML od Behavior do layout_behavior w powiązanym widoku przewijanym (takim jak RecyclerView lub NestedScrollView), aby zadeklarować, jak pasek narzędzi ma się zwijać/rozwijać podczas przewijania.

Podobny efekt możesz uzyskać w sekcji Utwórz za pomocą polecenia TopAppBarScrollBehavior. Aby np. zaimplementować pasek narzędzi zwijania/rozwijania, tak aby był on wyświetlany przy przewijaniu w górę, wykonaj te czynności:

  1. Wywołaj TopAppBarDefaults.enterAlwaysScrollBehavior(), aby utworzyć TopAppBarScrollBehavior.
  2. Przekaż utworzony element TopAppBarScrollBehavior elementowi TopAppBar.
  3. Połącz NestedScrollConnection za pomocą Modifier.nestedScroll w Scaffold, aby scaffold mógł odbierać zagnieżdżone zdarzenia przewijania podczas przewijania zawartości, którą można przewijać w górę i w dół. Dzięki temu pasek aplikacji podczas przewijania może się zwijać/rozwijać.

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

Dostosuj efekt zwijania/rozwijania przewijania

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

Aby utworzyć całkowicie niestandardowy efekt (np. efekt paralaksy), możesz też utworzyć własny element NestedScrollConnection i ręcznie odsunąć pasek narzędzi podczas przewijania treści. Przykładowy kod znajdziesz w artykule o zagnieżdżonym przewijaniu w AOSP.

Szuflady

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

W funkcji tworzenia wiadomości możesz wdrożyć panel nawigacji za pomocą funkcji kompozycyjnej ModalNavigationDrawer. Moduł ModalNavigationDrawer ma przedział drawerContent na panel i content na zawartość ekranu.

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

Więcej informacji znajdziesz w sekcji Suflady.

Paski powiadomień

Scaffold udostępnia przedział snackbarHost, który może zaakceptować funkcję SnackbarHost kompozycyjną do wyświetlenia 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 Paski powiadomień.

Więcej informacji

Więcej informacji na temat migracji elementu CoordinatorLayout do Compose znajdziesz w tych materiałach: