Créer une mise en page de volet secondaire

La mise en page canonique du volet secondaire attire l'attention de l'utilisateur 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 avec la vedette. Pour en savoir plus sur la mise en page canonique du volet secondaire, consultez les consignes concernant le volet secondaire Material 3.

Implémenter un volet secondaire

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

Le contenu principal occupe la majeure partie de l'écran, avec du contenu secondaire à côté.
Figure 1 : Mise en page du 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'

  • adaptative : éléments de base de bas niveau tels que HingeInfo et Posture
  • adaptive-layout : mises en page adaptatives, telles que SupportingPaneScaffold
  • adaptive-navigation : composables permettant de naviguer dans et entre les volets

Créer un navigateur et un échafaudage

Dans les petites fenêtres, un seul volet s'affiche à la fois. Utilisez donc 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 scaffoldDirective et scaffoldValue du navigateur:

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

Le volet principal et le volet secondaire sont des composables qui incluent votre contenu. Utilisez AnimatedPane pour appliquer les animations de volet par défaut lors de la navigation. Utilisez la valeur d'échafaudage 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 volets d'extraction

Extrayez 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 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 ce qui suit à 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() },
)