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 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. W tym fragmencie CoordinatorLayout zawiera AppBarLayout, który zawiera ToolBar, ViewPagerFloatingActionButton. 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 fragmentie lub aktywności uzyskaj odwołanie do dodanego właśnie elementu ComposeView i wywołaj metodę setContent. W treści metody ustaw Scaffold jako jej zawartość:

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

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 np. zaimplementować pasek narzędzi zwijania/rozwijania, tak aby był on wyświetlany podczas przewijania 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, 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łasną NestedScrollConnection i ręcznie przesuwać pasek narzędzi podczas przewijania treści. Przykładowy kod znajdziesz w artykule o zagnieżdżonym przewijaniu w AOSP.

Szuflady

W przypadku widoków schowanka nawigacyjna jest implementowana za pomocą widoku wyższego poziomu DrawerLayout. 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))
            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 na temat migracji elementu CoordinatorLayout do Compose znajdziesz w tych materiałach: