Przenieś układ koordynatora do tworzenia wiadomości

CoordinatorLayout to właściwość ViewGroup, która umożliwia stosowanie złożonych, nakładających się i zagnieżdżonych układów. Służy on jako kontener do obsługi określonych interakcji w stylu Material Design, np. rozwijania i zwijania pasków narzędzi czy dolnych arkuszy, w widokach, które się w nich znajdują.

W narzędziu Compose najbliższym odpowiednikiem funkcji CoordinatorLayout jest Scaffold. Element Scaffold udostępnia boksy treści do łączenia komponentów Material Design z typowymi wzorcami ekranów i interakcjami. Na tej stronie opisujemy, jak przenieść implementację CoordinatorLayout, aby używać interfejsu Scaffold w interfejsie Compose.

Etapy migracji

Aby przeprowadzić migrację domeny CoordinatorLayout do Scaffold, wykonaj te czynności:

  1. We fragmencie kodu poniżej CoordinatorLayout zawiera obiekt AppBarLayout zawierający ToolBar, ViewPager i FloatingActionButton. Skomentuj obiekt CoordinatorLayout i jego elementy podrzędne w hierarchii interfejsu użytkownika i dodaj do niego 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 sekcji Fragment lub Aktywność znajdź odniesienie do właśnie dodanego elementu ComposeView i wywołaj dla niego metodę setContent. W treści metody ustaw Scaffold jako jej treść:

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

  3. W treści aplikacji Scaffold dodaj główne treści z ekranu. Ponieważ główną treścią w powyższym pliku XML jest ViewPager2, użyliśmy elementu HorizontalPager, który jest odpowiednikiem tego elementu Compose. Funkcja lambda content elementu Scaffold również otrzymuje wystąpienie PaddingValues, które należy zastosować do katalogu głównego treści. Możesz użyć Modifier.padding, aby zastosować tę samą wartość PaddingValues do elementu HorizontalPager.

    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 z treściami udostępnianych przez Scaffold, aby dodać więcej elementów ekranu i przenieść pozostałe widoki podrzędne. Możesz użyć boksu topBar, aby dodać TopAppBar, i floatingActionButton, aby dodać element 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 przypadki użycia

Zwijanie i rozwijanie pasków narzędzi

Aby w systemie widoków zwinąć i rozwinąć pasek narzędzi za pomocą funkcji CoordinatorLayout, użyj AppBarLayout jako kontenera paska narzędzi. Następnie w powiązanym widoku z możliwością przewijania (np. RecyclerView lub NestedScrollView) możesz określić wartości od Behavior do layout_behavior w pliku XML, aby zadeklarować sposób zwijania/rozwijania paska narzędzi podczas przewijania.

Podobny efekt możesz uzyskać w funkcji Utwórz za pomocą narzędzia TopAppBarScrollBehavior. Aby np. zaimplementować pasek narzędzi zwijania/rozwijania, który wyświetla się podczas przewijania w górę, wykonaj te czynności:

  1. Zadzwoń pod numer TopAppBarDefaults.enterAlwaysScrollBehavior(), aby utworzyć TopAppBarScrollBehavior.
  2. Podaj utworzony TopAppBarScrollBehavior w: TopAppBar.
  3. Połącz NestedScrollConnection za pomocą Modifier.nestedScroll w elemencie Scaffold, aby scaffold mógł otrzymywać zagnieżdżone zdarzenia przewijania, gdy treść przewijana w górę lub w dół. Dzięki temu powiązany pasek aplikacji może się odpowiednio zwijać i rozwijać 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 przewijania zwijania i rozwijania

Aby dostosować efekt animacji zwijania/rozwijania, możesz podać kilka parametrów enterAlwaysScrollBehavior. TopAppBarDefaults udostępnia też inne funkcje TopAppBarScrollBehavior, np. exitUntilCollapsedScrollBehavior, które rozwijają pasek aplikacji tylko wtedy, gdy treść jest przewinięta do końca w dół.

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

Szuflady

W przypadku widoków możesz zaimplementować szufladę nawigacji, używając DrawerLayout jako widoku głównego. CoordinatorLayout jest natomiast widokiem podrzędnym elementu DrawerLayout. Element DrawerLayout zawiera też inny widok podrzędny, np. NavigationView, który wyświetla w szufladzie opcje nawigacji.

W oknie tworzenia wiadomości możesz wdrożyć panel nawigacji za pomocą funkcji kompozycyjnej ModalNavigationDrawer. ModalNavigationDrawer oferuje boks drawerContent na szufladę i miejsce 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 Panele.

Paski powiadomień

Scaffold udostępnia boks snackbarHost, który może akceptować funkcję SnackbarHost kompozycyjną do wyświetlenia elementu 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 o przenoszeniu elementu CoordinatorLayout do interfejsu Compose znajdziesz w tych materiałach: