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 używany jako kontener umożliwiający określone interakcje Material Design, takie jak rozwijanie i zwijanie pasków narzędzi oraz plansz dolnych, w przypadku widoków, które zawiera.

W Compose najbliższym odpowiednikiem CoordinatorLayout jest Scaffold. Scaffold udostępnia boksy na treści, które umożliwiają łączenie komponentów Material Design w typowe wzorce i interakcje na ekranie. Na tej stronie dowiesz się, jak przenieść implementację CoordinatorLayout, aby używać Scaffold w Compose.

Kroki migracji

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

  1. We fragmencie poniżej element CoordinatorLayout zawiera element AppBarLayout dla elementu zawierającego elementy ToolBar, ViewPager i FloatingActionButton. Zmień w komentarz element CoordinatorLayout i jego elementy podrzędne w hierarchii interfejsu i dodaj element ComposeView, aby go zastąpić.

    ```xml

    <!-- AppBarLayout contents here -->
    

    ```

  2. We fragmencie lub aktywności uzyskaj odwołanie do dodanego elementu ComposeView i wywołaj na nim metodę setContent. W treści metody ustaw Scaffold jako zawartość:

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

  3. W treści elementu Scaffold dodaj główną treść ekranu. Główną treścią w powyższym kodzie XML jest ViewPager2, więc użyjemy HorizontalPager, który jest jego odpowiednikiem w Compose. Funkcja lambda content elementu Scaffold otrzymuje też instancję PaddingValues, którą należy zastosować do katalogu głównego treści. Możesz użyć Modifier.padding, aby zastosować te same 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 boksów treści udostępnianych przez Scaffold, aby dodać więcej elementów ekranu i przenieść pozostałe widoki dziecka. Możesz użyć slotu topBar, aby dodać TopAppBar, i slotu floatingActionButton, aby dodać 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 przypadki użycia

Zwijanie i rozwijanie pasków narzędzi

W systemie widoków, aby zwijać i rozwijać pasek narzędzi za pomocą CoordinatorLayout, używasz AppBarLayout jako kontenera paska narzędzi. Następnie możesz określić Behavior do layout_behavior w pliku XML w powiązanym widoku przewijanym (np. RecyclerView lub NestedScrollView), aby zadeklarować, jak pasek narzędzi ma się zwijać i rozwijać podczas przewijania.

W Compose możesz uzyskać podobny efekt za pomocą TopAppBarScrollBehavior. Aby na przykład wdrożyć zwijany/rozwijany pasek narzędzi, który pojawia się po przewinięciu w górę, wykonaj te czynności:

  1. Wywołaj TopAppBarDefaults.enterAlwaysScrollBehavior(), aby utworzyć TopAppBarScrollBehavior.
  2. Przekaż utworzony TopAppBarScrollBehavior do TopAppBar.
  3. Połącz NestedScrollConnection za pomocą Modifier.nestedScroll w Scaffold, aby Scaffold mógł odbierać zagnieżdżone zdarzenia przewijania, gdy treść jest przewijana w górę lub w dół. Dzięki temu 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 ze zwijaniem/rozwijaniem

Możesz podać kilka parametrów dla enterAlwaysScrollBehavior, aby dostosować efekt animacji zwijania/rozwijania. TopAppBarDefaults udostępnia też inne TopAppBarScrollBehavior, takie jak exitUntilCollapsedScrollBehavior, które rozwija pasek aplikacji tylko wtedy, gdy treść jest przewijana do samego dołu.

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 AOSP.

Szuflady

W przypadku widoków panel nawigacji implementuje się, używając DrawerLayout jako widoku głównego. Z kolei CoordinatorLayout jest widokiem dziecka elementu DrawerLayout. DrawerLayout zawiera też inny widok podrzędny, np. NavigationView, który wyświetla opcje nawigacji w panelu.

W Compose możesz zaimplementować panel nawigacji za pomocą funkcji kompozycyjnej ModalNavigationDrawer. ModalNavigationDrawer udostępnia slot drawerContent na panel i slot 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 Szuflady.

Paski powiadomień

Scaffold udostępnia boks snackbarHost, który może przyjąć element kompozycyjny SnackbarHost do wyświetlania 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 migracji elementu CoordinatorLayout do Compose znajdziesz w tych materiałach: