Liste/Détail est un modèle d'interface utilisateur qui se compose d'une mise en page à deux volets, où un volet présente une liste d'éléments et un autre affiche les détails des éléments sélectionnés dans la liste.
Ce modèle est particulièrement utile pour les applications qui fournissent des informations détaillées sur les éléments de grandes collections, par exemple un client de messagerie contenant une liste d'e-mails et le contenu détaillé de chacun d'eux. Vous pouvez également utiliser la vue Liste/Détail pour les chemins d'accès moins critiques, par exemple pour diviser les préférences d'une application en une liste de catégories avec les préférences pour chaque catégorie dans le volet des détails.
Implémenter un modèle d'UI avec ListDetailPaneScaffold
ListDetailPaneScaffold
est un composable qui simplifie l'implémentation du modèle list-detail dans votre application. Une échafaudage liste/détails peut comporter jusqu'à trois volets: un volet de liste, un volet de détails et un volet supplémentaire facultatif. L'échafaudage gère les calculs d'espace à l'écran. Lorsque une taille d'écran suffisante est disponible, le volet de détails s'affiche à côté du volet de liste. Sur les petites tailles d'écran, l'échafaudage passe automatiquement à l'affichage en plein écran du volet de liste ou de détail.
![Volet détaillé affiché à côté de la page de liste.](https://developer.android.com/static/develop/ui/compose/images/layouts/adaptive/list-detail-2.png?authuser=7&hl=fr)
![Une fois qu'un élément est sélectionné, le volet Détails occupe la totalité de l'écran.](https://developer.android.com/static/develop/ui/compose/images/layouts/adaptive/list-detail-1.png?authuser=7&hl=fr)
Déclarer des dépendances
ListDetailPaneScaffold
fait partie de la bibliothèque de mises en page adaptatives Material 3.
Votre application doit inclure des dépendances pour trois bibliothèques Material 3 associées:
- adaptatif : composants de base tels que
HingeInfo
etPosture
- adaptive-layout : mises en page adaptatives telles que
ListDetailPaneScaffold
etSupportingPaneScaffold
- adaptive-navigation : composables permettant de naviguer dans et entre les volets
Ajoutez les dépendances au fichier build.gradle
de votre application ou module:
Kotlin
implementation("androidx.compose.material3.adaptive:adaptive:1.0.0-alpha12") implementation("androidx.compose.material3.adaptive:adaptive-layout:1.0.0-alpha12") implementation("androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-alpha12")
Groovy
implementation 'androidx.compose.material3.adaptive:adaptive:1.0.0-alpha12' implementation 'androidx.compose.material3.adaptive:adaptive-layout:1.0.0-alpha12' implementation 'androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-alpha12'
Utilisation de base
Implémentez ListDetailPaneScaffold
comme suit:
Utilisez une classe représentant le contenu à sélectionner. Cette classe doit être
Parcelable
pour permettre l'enregistrement et la restauration de l'élément de liste sélectionné. Utilisez le plug-in kotlin-parcelize afin de générer le code automatiquement.@Parcelize class MyItem(val id: Int) : Parcelable
Créez un
ThreePaneScaffoldNavigator
avecrememberListDetailPaneScaffoldNavigator
et ajoutez unBackHandler
. Cet outil de navigation permet de naviguer entre les volets de liste, de détails et supplémentaires. En déclarant un type générique, le navigateur suit également l'état de l'échafaudage (c'est-à-dire l'élémentMyItem
affiché). Étant donné que ce type est parcelable, l'état peut être enregistré et restauré par le navigateur pour gérer automatiquement les modifications de configuration.BackHandler
permet de revenir en arrière à l'aide du geste ou du bouton Retour du système. Le comportement attendu du bouton "Retour" pour unListDetailPaneScaffold
dépend de la taille de la fenêtre et de la valeur actuelle de l'échafaudage. SiListDetailPaneScaffold
permet de revenir à l'état actuel,canNavigateBack()
esttrue
, ce qui activeBackHandler
.val navigator = rememberListDetailPaneScaffoldNavigator<MyItem>() BackHandler(navigator.canNavigateBack()) { navigator.navigateBack() }
Transmettez le
scaffoldState
denavigator
au composableListDetailPaneScaffold
.ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, // ... )
Fournissez l'implémentation de votre volet de liste à
ListDetailPaneScaffold
. UtilisezAnimatedPane
pour appliquer les animations de volet par défaut lors de la navigation. Utilisez ensuiteThreePaneScaffoldNavigator
pour accéder au volet des détails,ListDetailPaneScaffoldRole.Detail
, et afficher l'élément transmis.ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, listPane = { AnimatedPane { MyList( onItemClick = { item -> // Navigate to the detail pane with the passed item navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item) } ) } }, // ... )
Incluez l'implémentation de votre volet de détails dans
ListDetailPaneScaffold
. Une fois la navigation terminée,currentDestination
contient le volet auquel votre application a accédé, y compris le contenu affiché dans celui-ci. La propriétécontent
est du même type que celui spécifié dans l'appel de remember d'origine (MyItem
dans cet exemple). Vous pouvez donc également y accéder pour toutes les données que vous devez afficher.ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, listPane = // ... detailPane = { AnimatedPane { navigator.currentDestination?.content?.let { MyDetails(it) } } }, )
Une fois les étapes ci-dessus mises en œuvre, votre code doit ressembler à ce qui suit:
val navigator = rememberListDetailPaneScaffoldNavigator<MyItem>() BackHandler(navigator.canNavigateBack()) { navigator.navigateBack() } ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, listPane = { AnimatedPane { MyList( onItemClick = { item -> // Navigate to the detail pane with the passed item navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item) }, ) } }, detailPane = { AnimatedPane { // Show the detail pane content if selected item is available navigator.currentDestination?.content?.let { MyDetails(it) } } }, )