Esegui la migrazione di CoordinatorLayout in Compose

CoordinatorLayout è un ViewGroup che consente layout complessi, sovrapposti e nidificati. Viene utilizzato come contenitore per attivare interazioni specifiche di Material Design, ad esempio barre degli strumenti di espansione/compressione e fogli inferiori, per le viste contenute al suo interno.

In Compose, l'equivalente più vicino di CoordinatorLayout è un Scaffold. Un elemento Scaffold fornisce aree di contenuto per combinare i componenti Material in interazioni e pattern dello schermo comuni. In questa pagina viene descritto come eseguire la migrazione dell'implementazione di CoordinatorLayout per utilizzare Scaffold in Compose.

Passaggi della migrazione

Per eseguire la migrazione di CoordinatorLayout a Scaffold, segui questi passaggi:

  1. Nello snippet seguente, CoordinatorLayout contiene un AppBarLayout per contenere un ToolBar, un ViewPager e un FloatingActionButton. Commenta CoordinatorLayout e i relativi elementi secondari dalla gerarchia dell'interfaccia utente e aggiungi un ComposeView per sostituirlo.

    <!--  <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. In Frammento o Attività, recupera un riferimento al ComposeView che hai appena aggiunto e chiama il metodo setContent. Nel corpo del metodo, imposta Scaffold come contenuto:

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

  3. Nei contenuti di Scaffold, aggiungi i contenuti principali dello schermo. Poiché il contenuto principale nel file XML riportato sopra è di tipo ViewPager2, utilizzeremo HorizontalPager, che è l'equivalente di Compose. La funzione lambda content di Scaffold riceve anche un'istanza di PaddingValues che deve essere applicata alla radice dei contenuti. Puoi utilizzare Modifier.padding per applicare lo stesso PaddingValues a HorizontalPager.

    composeView.setContent {
        Scaffold(Modifier.fillMaxSize()) { contentPadding ->
            val pagerState = rememberPagerState {
                10
            }
            HorizontalPager(
                state = pagerState,
                modifier = Modifier.padding(contentPadding)
            ) { /* Page contents */ }
        }
    }

  4. Utilizza le altre aree dei contenuti fornite da Scaffold per aggiungere altri elementi dello schermo ed eseguire la migrazione delle visualizzazioni secondarie rimanenti. Puoi utilizzare l'area topBar per aggiungere un TopAppBar e l'area floatingActionButton per fornire un 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 */ }
        }
    }

Casi d'uso comuni

Comprimi ed espandi le barre degli strumenti

Nel sistema di visualizzazione, per comprimere ed espandere la barra degli strumenti con CoordinatorLayout, utilizza un AppBarLayout come contenitore per la barra degli strumenti. Puoi quindi specificare un valore da Behavior a layout_behavior in XML nella visualizzazione scorrevole associata (come RecyclerView o NestedScrollView) per dichiarare in che modo la barra degli strumenti si comprime/si espande mentre scorri.

In Compose, puoi ottenere un effetto simile tramite una TopAppBarScrollBehavior. Ad esempio, per implementare una barra degli strumenti che si comprime/espandi in modo che venga visualizzata quando scorri verso l'alto, procedi nel seguente modo:

  1. Chiama TopAppBarDefaults.enterAlwaysScrollBehavior() per creare un TopAppBarScrollBehavior.
  2. Fornisci il valore TopAppBarScrollBehavior creato a TopAppBar.
  3. Connetti NestedScrollConnection tramite Modifier.nestedScroll sul Scaffold in modo che l'impalcatura possa ricevere eventi di scorrimento nidificati mentre i contenuti scorribili scorrono verso l'alto o verso il basso. In questo modo, la barra dell'app contenuta può comprimersi/espandersi in modo appropriato mentre i contenuti scorrono.

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

Personalizza l'effetto di scorrimento di compressione/espansione

Puoi fornire diversi parametri per enterAlwaysScrollBehavior per personalizzare l'effetto dell'animazione di compressione/espansione. TopAppBarDefaults fornisce anche altri TopAppBarScrollBehavior come exitUntilCollapsedScrollBehavior, che espande la barra dell'app solo quando i contenuti vengono fatti scorrere fino in fondo.

Per creare un effetto completamente personalizzato (ad esempio un effetto parallasse), puoi creare un elemento NestedScrollConnection personalizzato e spostare manualmente la barra degli strumenti mentre i contenuti scorrono. Per un esempio di codice, consulta Esempio di scorrimento nidificato su AOSP.

Cassetti

Con le viste, puoi implementare un riquadro di navigazione a scomparsa utilizzando una DrawerLayout come vista principale. A sua volta, CoordinatorLayout è una visualizzazione secondaria di DrawerLayout. L'elemento DrawerLayout contiene anche un'altra vista secondaria, ad esempio NavigationView, per mostrare le opzioni di navigazione nel riquadro a scomparsa.

In Compose, puoi implementare un riquadro di navigazione a scomparsa utilizzando l'elemento componibile ModalNavigationDrawer. ModalNavigationDrawer offre uno slot drawerContent per il riquadro a scomparsa e uno slot content per i contenuti dello schermo.

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

Per scoprire di più, consulta Riquadro a scomparsa.

Snackbar

Scaffold offre un'area snackbarHost che può accettare un componibile SnackbarHost per visualizzare un 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
    // ...
}

Per scoprire di più, consulta la sezione Snackbar.

Scopri di più

Per maggiori informazioni sulla migrazione di un CoordinatorLayout a Compose, consulta le risorse seguenti: