Migrer CoordinatorLayout vers Compose

CoordinatorLayout est un ViewGroup qui permet des tâches complexes, de chevauchement et mises en page imbriquées. Il est utilisé comme conteneur pour permettre l'utilisation de Material Design les interactions, telles que le développement/la réduction des barres d'outils et des bottom sheets, pour les vues. qu'il contient.

Dans Compose, l'équivalent le plus proche d'un CoordinatorLayout est un Scaffold Un Scaffold fournit des emplacements de contenu pour combiner Material des composants dans des modèles d'écran et des interactions courants ; Cette page explique comment vous pouvez migrer votre implémentation de CoordinatorLayout pour utiliser Scaffold dans Nouveau message.

Procédure de migration

Pour migrer CoordinatorLayout vers Scaffold, procédez comme suit:

  1. Dans l'extrait ci-dessous, CoordinatorLayout contient un AppBarLayout pour contenant un ToolBar, un ViewPager et un FloatingActionButton. Ajouter un commentaire Extrayez CoordinatorLayout et ses enfants de la hiérarchie de votre UI, puis ajoutez une ComposeView pour le remplacer.

    <!--  <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. Dans votre fragment ou votre activité, obtenez une référence au ComposeView que vous que vous venez d'ajouter et d'y appeler la méthode setContent. Dans le corps de la méthode, définissez un Scaffold comme contenu:

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

  3. Dans le contenu de votre Scaffold, ajoutez le contenu principal de votre écran sous Comme le contenu principal du code XML ci-dessus est un ViewPager2, nous utiliserons HorizontalPager, qui en est l'équivalent dans Compose. Le lambda content de Scaffold reçoit également une instance de PaddingValues qui doit être appliquée à la racine du contenu. Vous pouvez utiliser Modifier.padding pour appliquer la même PaddingValues sur HorizontalPager.

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

  4. Utilisez d'autres emplacements de contenu fournis par Scaffold pour ajouter d'autres éléments à l'écran et migrer les vues enfants restantes. Vous pouvez utiliser l'emplacement topBar pour ajouter TopAppBar et l'emplacement floatingActionButton pour fournir 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 */ }
        }
    }

Cas d'utilisation courants

Réduire et développer les barres d'outils

Dans le système de vues, pour réduire et développer la barre d'outils avec CoordinatorLayout, procédez comme suit : vous utilisez un AppBarLayout comme conteneur pour la barre d'outils. Vous pouvez ensuite spécifier Behavior à layout_behavior en XML sur l'élément déroulant associé Affichez (comme RecyclerView ou NestedScrollView) pour déclarer comment la barre d'outils se réduit/se développe au fur et à mesure que vous faites défiler la page.

Dans Compose, vous pouvez obtenir un effet similaire TopAppBarScrollBehavior Par exemple, pour mettre en œuvre une stratégie de repli/d'expansion barre d'outils de sorte qu'elle apparaisse lorsque vous faites défiler la page vers le haut, procédez comme suit:

  1. Appelez TopAppBarDefaults.enterAlwaysScrollBehavior() pour créer un TopAppBarScrollBehavior
  2. Fournissez le TopAppBarScrollBehavior créé à TopAppBar.
  3. Connectez le NestedScrollConnection via Modifier.nestedScroll sur le Scaffold afin que l'échafaudage (Scaffold) puisse recevoir des événements de défilement imbriqué en tant que le contenu déroulant défile vers le haut/bas. De cette façon, la barre d'application contenue peut se réduire ou se développer de manière appropriée à mesure que le contenu défile ;

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

Personnaliser l'effet de défilement qui se réduit ou qui se développe

Vous pouvez fournir plusieurs paramètres pour enterAlwaysScrollBehavior afin de personnaliser l'effet d'animation de réduction/d'expansion. TopAppBarDefaults également fournit d'autres TopAppBarScrollBehavior, comme exitUntilCollapsedScrollBehavior, qui ne développe la barre d'application que lorsque on fait défiler le contenu jusqu'en bas.

Pour créer un effet entièrement personnalisé (par exemple, un effet de parallaxe), vous pouvez créer votre propre NestedScrollConnection et décaler la barre d'outils manuellement le contenu défile. Consultez l'exemple de défilement imbriqué sur AOSP pour découvrir exemple de code.

Panneaux

Avec les vues, vous pouvez implémenter un panneau de navigation à l'aide d'un DrawerLayout comme vue racine. De son côté, votre CoordinatorLayout est vue enfant de DrawerLayout. Le DrawerLayout contient également un autre enfant. (NavigationView, par exemple), pour afficher les options de navigation dans la panneau.

Dans Compose, vous pouvez implémenter un panneau de navigation à l'aide de la méthode ModalNavigationDrawer. ModalNavigationDrawer propose un Emplacement drawerContent pour le panneau et emplacement content pour les emplacements de l'écran contenus.

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

Pour en savoir plus, consultez la section Panneaux.

Snackbars

Scaffold fournit un emplacement snackbarHost, qui peut accepter un SnackbarHost. composable pour afficher 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
    // ...
}

Pour en savoir plus, consultez la page Snackbars.

En savoir plus

Pour en savoir plus sur la migration d'un CoordinatorLayout vers Compose, consultez la ressources suivantes: