Créer une mise en page de volet secondaire

La mise en page canonique du volet secondaire attire l'attention des utilisateurs sur le contenu principal de votre application tout en affichant du contenu secondaire pertinent. Par exemple, le volet de contenu principal peut afficher des informations sur un film récent, tandis que le volet secondaire affiche une liste d'autres films ayant un thème similaire, ou du même réalisateur ou acteurs. Pour en savoir plus sur la mise en page canonique du volet secondaire, consultez les consignes relatives aux volets secondaires de Material 3.

Implémenter un volet secondaire

SupportingPaneScaffold comprend jusqu'à trois volets: un volet principal, un volet secondaire et un volet supplémentaire facultatif. L'échafaudage gère tous les calculs d'allocation d'espace de fenêtre aux trois volets. Sur les grands écrans, l'échafaudage affiche le volet principal et le volet secondaire sur le côté. Sur les petits écrans, l'échafaudage affiche en plein écran le volet principal ou le volet secondaire.

Contenu principal occupant la majeure partie de l'écran, accompagné de contenus secondaires
Figure 1 : Mise en page avec volet secondaire

Ajouter des dépendances

SupportingPaneScaffold fait partie de la bibliothèque de mise en page adaptative Material 3.

Ajoutez les trois dépendances associées suivantes au fichier build.gradle de votre application ou module:

Kotlin


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

Groovy


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

  • adaptatif : composants de base de bas niveau, tels que HingeInfo et Posture
  • adaptive-layout : mises en page adaptatives telles que SupportingPaneScaffold
  • adaptive-navigation (navigation adaptative) : composables permettant de naviguer dans les volets et entre eux

Créer un navigateur et un échafaudage

Dans les fenêtres de petite taille, un seul volet ne s'affiche à la fois. Vous devez donc utiliser un ThreePaneScaffoldNavigator pour passer d'un volet à l'autre. Créez une instance du navigateur avec rememberSupportingPaneScaffoldNavigator. Pour gérer les gestes Retour, utilisez un BackHandler qui vérifie canNavigateBack() et appelle navigateBack():

val navigator = rememberSupportingPaneScaffoldNavigator()

BackHandler(navigator.canNavigateBack()) {
    navigator.navigateBack()
}

L'échafaudage nécessite un PaneScaffoldDirective, qui contrôle comment diviser l'écran et l'espacement à utiliser, et un ThreePaneScaffoldValue, qui fournit l'état actuel des volets (par exemple, s'ils sont développés ou masqués). Pour le comportement par défaut, utilisez respectivement les valeurs scaffoldDirective et scaffoldValue du navigateur:

SupportingPaneScaffold(
    directive = navigator.scaffoldDirective,
    value = navigator.scaffoldValue,
    mainPane = { /*...*/ },
    supportingPane = { /*...*/ },
)

Le volet principal et le volet secondaire sont des composables contenant votre contenu. Utilisez AnimatedPane pour appliquer les animations de volet par défaut pendant la navigation. Utilisez la valeur scaffold pour vérifier si le volet secondaire est masqué. Le cas échéant, affichez un bouton qui appelle navigateTo(ThreePaneScaffoldRole.Secondary) pour afficher le volet secondaire.

Voici une implémentation complète de l'échafaudage:

val navigator = rememberSupportingPaneScaffoldNavigator()

BackHandler(navigator.canNavigateBack()) {
    navigator.navigateBack()
}

SupportingPaneScaffold(
    directive = navigator.scaffoldDirective,
    value = navigator.scaffoldValue,
    mainPane = {
        AnimatedPane(modifier = Modifier.safeContentPadding()) {
            // Main pane content
            if (navigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Hidden) {
                Button(
                    modifier = Modifier.wrapContentSize(),
                    onClick = {
                        navigator.navigateTo(SupportingPaneScaffoldRole.Supporting)
                    }
                ) {
                    Text("Show supporting pane")
                }
            } else {
                Text("Supporting pane is shown")
            }
        }
    },
    supportingPane = {
        AnimatedPane(modifier = Modifier.safeContentPadding()) {
            // Supporting pane content
            Text("Supporting pane")
        }
    },
)

Composables de volet d'extraction

Extraire les volets individuels d'un SupportingPaneScaffold dans leurs propres composables pour les rendre réutilisables et testables. Utilisez ThreePaneScaffoldScope pour accéder à AnimatedPane si vous souhaitez utiliser les animations par défaut:

@Composable
fun ThreePaneScaffoldScope.MainPane(
    shouldShowSupportingPaneButton: Boolean,
    onNavigateToSupportingPane: () -> Unit,
    modifier: Modifier = Modifier,
) {
    AnimatedPane(modifier = modifier.safeContentPadding()) {
        // Main pane content
        if (shouldShowSupportingPaneButton) {
            Button(onClick = onNavigateToSupportingPane) {
                Text("Show supporting pane")
            }
        } else {
            Text("Supporting pane is shown")
        }
    }
}

@Composable
fun ThreePaneScaffoldScope.SupportingPane(
    modifier: Modifier = Modifier,
) {
    AnimatedPane(modifier = modifier.safeContentPadding()) {
        // Supporting pane content
        Text("This is the supporting pane")
    }
}

L'extraction des volets en composables simplifie l'utilisation de SupportingPaneScaffold (comparez les éléments suivants à l'implémentation complète de l'échafaudage dans la section précédente):

val navigator = rememberSupportingPaneScaffoldNavigator()

BackHandler(navigator.canNavigateBack()) {
    navigator.navigateBack()
}

SupportingPaneScaffold(
    directive = navigator.scaffoldDirective,
    value = navigator.scaffoldValue,
    mainPane = {
        MainPane(
            shouldShowSupportingPaneButton = navigator.scaffoldValue.secondary == PaneAdaptedValue.Hidden,
            onNavigateToSupportingPane = { navigator.navigateTo(ThreePaneScaffoldRole.Secondary) }
        )
    },
    supportingPane = { SupportingPane() },
)