Créer une navigation adaptative

La plupart des applications disposent de quelques destinations de premier niveau accessibles via le l'UI de navigation principale de l'application. Dans les fenêtres compactes, telles qu'un téléphone standard les destinations sont généralement affichées dans une barre de navigation en bas de la fenêtre. Dans une fenêtre développée, telle qu'une application en plein écran sur un sur votre tablette, un rail de navigation à côté de l'application est généralement plus adapté, car Les commandes de navigation sont plus faciles d'accès en maintenant les côtés gauche et droit enfoncés. de l'appareil.

NavigationSuiteScaffold simplifie le changement entre les interfaces utilisateur de navigation en affichant le composable approprié d'interface utilisateur de navigation basée sur WindowSizeClass. Cela inclut de manière dynamique modifier l'UI lors d'un changement de taille de la fenêtre d'exécution. Le comportement par défaut est afficher l'un des composants d'interface utilisateur suivants:

  • Barre de navigation si la largeur ou la hauteur sont compactes, ou si l'appareil est en position à plat
  • Rail de navigation pour tout le reste
<ph type="x-smartling-placeholder">
</ph>
Figure 1 : NavigationSuiteScaffold affiche une barre de navigation dans les fenêtres compactes.
<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Figure 2 : NavigationSuiteScaffold affiche un rail de navigation dans les fenêtres développées.

Ajouter des dépendances

NavigationSuiteScaffold fait partie de Suite de navigation adaptative Material3 bibliothèque. Ajoutez une dépendance pour la bibliothèque dans le fichier build.gradle de votre application ou module:

Kotlin


implementation("androidx.compose.material3:material3-adaptive-navigation-suite")

Groovy


implementation 'androidx.compose.material3:material3-adaptive-navigation-suite'

Créer un échafaudage

Les deux parties principales de NavigationSuiteScaffold sont les éléments de la suite de navigation et le contenu pour la destination sélectionnée. Vous pouvez définir directement les éléments de la suite de navigation dans un composable, mais il est courant qu'ils soient définis ailleurs, par exemple dans une énumération:

enum class AppDestinations(
    @StringRes val label: Int,
    val icon: ImageVector,
    @StringRes val contentDescription: Int
) {
    HOME(R.string.home, Icons.Default.Home, R.string.home),
    FAVORITES(R.string.favorites, Icons.Default.Favorite, R.string.favorites),
    SHOPPING(R.string.shopping, Icons.Default.ShoppingCart, R.string.shopping),
    PROFILE(R.string.profile, Icons.Default.AccountBox, R.string.profile),
}

Pour utiliser NavigationSuiteScaffold, vous devez suivre la destination actuelle, qui vous pouvez le faire à l'aide de rememberSaveable:

var currentDestination by rememberSaveable { mutableStateOf(AppDestinations.HOME) }

Dans l'exemple suivant, le paramètre navigationSuiteItems (type NavigationSuiteScope utilise sa fonction item. pour définir l'UI de navigation pour une destination individuelle. L'UI de destination est utilisé dans les barres de navigation, les rails et les panneaux. Pour créer des éléments de navigation, vous une boucle sur votre AppDestinations (définie dans l'extrait précédent):

NavigationSuiteScaffold(
    navigationSuiteItems = {
        AppDestinations.entries.forEach {
            item(
                icon = {
                    Icon(
                        it.icon,
                        contentDescription = stringResource(it.contentDescription)
                    )
                },
                label = { Text(stringResource(it.label)) },
                selected = it == currentDestination,
                onClick = { currentDestination = it }
            )
        }
    }
) {
    // TODO: Destination content.
}

Dans le lambda du contenu de destination, utilisez la valeur currentDestination pour décider quelle UI afficher. Si vous utilisez une bibliothèque de navigation dans votre application, utilisez-la ici pour afficher la destination appropriée. Une instruction "when" peut suffire:

NavigationSuiteScaffold(
    navigationSuiteItems = { /*...*/ }
) {
    // Destination content.
    when (currentDestination) {
        AppDestinations.HOME -> HomeDestination()
        AppDestinations.FAVORITES -> FavoritesDestination()
        AppDestinations.SHOPPING -> ShoppingDestination()
        AppDestinations.PROFILE -> ProfileDestination()
    }
}

Modifier les couleurs

NavigationSuiteScaffold crée un Surface sur toute la zone l'échafaudage occupe généralement la fenêtre complète. En plus de cela, l'échafaudage dessine l'UI de navigation particulière, par exemple un NavigationBar. La surface et l'UI de navigation utilisent les valeurs spécifiées dans le fichier du thème, mais vous pouvez remplacer les valeurs du thème.

Le paramètre containerColor spécifie la couleur de la surface. La valeur par défaut est la couleur d'arrière-plan de votre jeu de couleurs. Le paramètre contentColor spécifie la couleur du contenu sur cette surface. La fonction est "activée" par défaut. couleur [color] de ce qui est spécifié pour containerColor. Par exemple, si containerColor utilise la couleur background, alors contentColor utilise la couleur onBackground. Consultez Thématisation Material Design 3 dans Compose. pour en savoir plus sur le fonctionnement du système de couleurs. Lorsque vous remplacez ces valeurs, Utiliser les valeurs définies dans votre thème pour que votre application soit compatible avec les affichages sombre et clair modes:

NavigationSuiteScaffold(
    navigationSuiteItems = { /* ... */ },
    containerColor = MaterialTheme.colorScheme.primary,
    contentColor = MaterialTheme.colorScheme.onPrimary,
) {
    // Content...
}

L'UI de navigation est dessinée devant la surface NavigationSuiteScaffold. Les valeurs par défaut des couleurs de l'interface utilisateur sont fournies par NavigationSuiteDefaults.colors(), mais vous peuvent également remplacer ces valeurs. Par exemple, si vous souhaitez que l'arrière-plan la barre de navigation doit être transparente, mais les autres valeurs sont les valeurs par défaut, remplacer navigationBarContainerColor:

NavigationSuiteScaffold(
    navigationSuiteItems = { /* ... */ },
    navigationSuiteColors = NavigationSuiteDefaults.colors(
        navigationBarContainerColor = Color.Transparent,
    )
) {
    // Content...
}

En fin de compte, vous pouvez personnaliser chaque élément de l'interface utilisateur de navigation. Lorsque vous appelez la méthode item, vous pouvez transmettre une instance de NavigationSuiteItemColors La classe spécifie les couleurs des éléments d'une barre de navigation, d'un rail de navigation et d'un élément de navigation panneau. Cela signifie que vous pouvez avoir des couleurs identiques pour chaque type d'UI de navigation, ou vous pouvez varier les couleurs en fonction de vos besoins. Définissez les couleurs au niveau Niveau NavigationSuiteScaffold pour utiliser la même instance d'objet pour tous les éléments et appelez la fonction NavigationSuiteDefaults.itemColors() pour remplacer uniquement ceux que vous souhaitez modifier:

val myNavigationSuiteItemColors = NavigationSuiteDefaults.itemColors(
    navigationBarItemColors = NavigationBarItemDefaults.colors(
        indicatorColor = MaterialTheme.colorScheme.primaryContainer,
        selectedIconColor = MaterialTheme.colorScheme.onPrimaryContainer
    ),
)

NavigationSuiteScaffold(
    navigationSuiteItems = {
        AppDestinations.entries.forEach {
            item(
                icon = {
                    Icon(
                        it.icon,
                        contentDescription = stringResource(it.contentDescription)
                    )
                },
                label = { Text(stringResource(it.label)) },
                selected = it == currentDestination,
                onClick = { currentDestination = it },
                colors = myNavigationSuiteItemColors,
            )
        }
    },
) {
    // Content...
}

Personnaliser les types de navigation

Le comportement par défaut de NavigationSuiteScaffold modifie l'UI de navigation basé sur la taille de la fenêtre classes. Cependant, vous vous pouvez ignorer ce comportement. Par exemple, si votre application affiche un seul d'un grand volet de contenu pour un flux, l'application peut utiliser une navigation permanente pour les fenêtres étendues tout en revenant au comportement par défaut Classes de taille de fenêtre compacte et moyenne:

val adaptiveInfo = currentWindowAdaptiveInfo()
val customNavSuiteType = with(adaptiveInfo) {
    if (windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.EXPANDED) {
        NavigationSuiteType.NavigationDrawer
    } else {
        NavigationSuiteScaffoldDefaults.calculateFromAdaptiveInfo(adaptiveInfo)
    }
}

NavigationSuiteScaffold(
    navigationSuiteItems = { /* ... */ },
    layoutType = customNavSuiteType,
) {
    // Content...
}

Ressources supplémentaires

Consultez les conseils sur Material Design:

Consultez les composants suivants de la bibliothèque androidx.compose.material3: