Créer une mise en page liste/détails

La mise en page liste/détails est un schéma d'interface utilisateur qui se compose d'une mise en page à deux volets, dans laquelle un volet présente une liste d'éléments et un autre volet affiche les détails des éléments sélectionnés dans la liste.

Ce schéma 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 qui comporte une liste d'e-mails et le contenu détaillé de chaque message. La mise en page liste/détails peut également être utilisée pour des chemins moins critiques, par exemple pour diviser les préférences de l'application en une liste de catégories, avec les préférences de chaque catégorie dans le volet de détails.

Un volet de détails affiché à côté de la page de liste.
Figure 1. Lorsque la taille de l'écran est suffisante, le volet de détails s'affiche à côté du volet de liste.
Une fois un élément sélectionné, le volet de vue détaillée occupe tout l'écran.
Figure 2. Lorsque la taille de l'écran est limitée, le volet de détails (puisqu'un élément a été sélectionné) occupe tout l'espace.

Implémenter le schéma liste/détails avec NavigableListDetailPaneScaffold

NavigableListDetailPaneScaffold est un composable qui simplifie l'implémentation d'une mise en page liste/détails dans Jetpack Compose. Il encapsule ListDetailPaneScaffold et ajoute une navigation intégrée et des animations de prévisualisation du Retour.

Une structure liste/détails peut comporter jusqu'à trois volets :

  1. Volet de liste : affiche une collection d'éléments.
  2. Volet de détails : affiche les détails d’un élément sélectionné.
  3. Volet supplémentaire (facultatif) : fournit un contexte supplémentaire si nécessaire.

La structure s'adapte en fonction de la taille de la fenêtre :

  • Dans les grandes fenêtres, les volets de liste et de détails s'affichent côte à côte.
  • Dans les petites fenêtres, un seul volet est visible à la fois, et il change lorsque l'utilisateur navigue.

Déclarer des dépendances

NavigableListDetailPaneScaffold fait partie de la bibliothèque de navigation 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'
  • adaptive : composants de base de bas niveau tels que HingeInfo et Posture
  • adaptive-layout : mises en page adaptatives telles que ListDetailPaneScaffold et SupportingPaneScaffold
  • adaptive-navigation : composables pour naviguer dans les volets et entre eux, ainsi que des mises en page adaptatives qui prennent en charge la navigation par défaut, telles que NavigableListDetailPaneScaffold et NavigableSupportingPaneScaffold

Assurez-vous que votre projet inclut la version 1.1.0-beta1 ou une version ultérieure de compose-material3-adaptive.

Activer la prévisualisation du geste Retour

Pour activer les animations de prévisualisation du Retour dans Android 15 ou une version antérieure, vous devez activer la prise en charge de la prévisualisation du geste Retour. Pour ce faire, ajoutez android:enableOnBackInvokedCallback="true" à la balise <application> ou à des balises <activity> individuelles dans votre fichier AndroidManifest.xml. Pour en savoir plus, consultez Activer la prévisualisation du geste Retour.

Une fois que votre application cible Android 16 (niveau d'API 36) ou une version ultérieure, la prévisualisation du Retour est activée par défaut.

Utilisation de base

Implémentez NavigableListDetailPaneScaffold comme suit :

  1. Utilisez une classe qui représente le contenu sélectionné. Utilisez une Parcelable classe pour enregistrer et restaurer l'élément de liste sélectionné. Utilisez le plug-in kotlin-parcelize pour générer le code à votre place.
  2. Créez un ThreePaneScaffoldNavigator avec rememberListDetailPaneScaffoldNavigator.

Ce navigateur permet de passer des volets de liste, de détails et supplémentaires. En déclarant un type générique, le navigateur suit également l'état de la structure (c'est-à-dire le MyItem qui est affiché). Comme ce type est parcelable, l'état peut être enregistré et restauré par le navigateur pour gérer automatiquement les modifications de configuration.

  1. Transmettez le navigateur au composable NavigableListDetailPaneScaffold.

  2. Fournissez l'implémentation de votre volet de liste à NavigableListDetailPaneScaffold. Utilisez AnimatedPane pour appliquer les animations de volet par défaut lors de la navigation. Utilisez ensuite ThreePaneScaffoldNavigator pour accéder au volet de détails, ListDetailPaneScaffoldRole.Detail, et afficher l'élément transmis.

  3. Incluez l'implémentation de votre volet de détails dans NavigableListDetailPaneScaffold.

Une fois la navigation terminée, currentDestination contient le volet vers lequel votre application a navigué, y compris le contenu affiché dans le volet. La propriété contentKey est du même type que celui spécifié dans l'appel d'origine. Vous pouvez donc accéder à toutes les données que vous devez afficher.

  1. Vous pouvez également modifier le defaultBackBehavior dans NavigableListDetailPaneScaffold. Par défaut, NavigableListDetailPaneScaffold utilise PopUntilScaffoldValueChange pour defaultBackBehavior.

Si votre application nécessite un schéma de navigation "retour en arrière" différent, vous pouvez remplacer ce comportement en spécifiant une autre option BackNavigationBehavior.

Options BackNavigationBehavior

La section suivante utilise l'exemple d'une application de messagerie avec une liste d'e-mails dans un volet et une vue détaillée dans l'autre.

Ce comportement se concentre sur les modifications apportées à la structure globale de la mise en page. Dans une configuration à plusieurs volets, la modification du contenu de l'e-mail dans le volet de détails n'altère pas la structure de mise en page sous-jacente. Par conséquent, le bouton Retour peut quitter l'application ou le graphique de navigation actuel, car aucune modification de mise en page n'est à rétablir dans le contexte actuel. Dans une mise en page à un seul volet, appuyer sur le bouton Retour permet de passer d'une modification de contenu à l'autre dans la vue détaillée et de revenir à la vue de liste, car cela représente une modification claire de la mise en page.

Prenons les exemples suivants :

  • Plusieurs volets : vous consultez un e-mail (élément 1) dans le volet de détails. Si vous cliquez sur un autre e-mail (élément 2), le volet de détails est mis à jour, mais les volets de liste et de détails restent visibles. Appuyer sur le bouton Retour peut quitter l'application ou le flux de navigation actuel.
  • Un seul volet : vous consultez l'élément 1, puis l'élément 2. Si vous appuyez sur le bouton Retour, vous revenez directement au volet de la liste d'e-mails.

Utilisez cette option lorsque vous souhaitez que les utilisateurs perçoivent des transitions de mise en page distinctes à chaque action de retour.

Modification de la valeur de navigation.
PopUntilContentChange

Ce comportement donne la priorité au contenu affiché. Si vous consultez l'élément 1, puis l'élément 2, appuyer sur le bouton Retour rétablit l'élément 1, quelle que soit la mise en page.

Prenons les exemples suivants :

  • Plusieurs volets : vous consultez l'élément 1 dans le volet de détails, puis cliquez sur l'élément 2 dans la liste. Le volet de détails est mis à jour. Appuyer sur le bouton Retour rétablit l'élément 1 dans le volet de détails.
  • Un seul volet : la même inversion de contenu se produit.

Utilisez cette option lorsque l'utilisateur s'attend à revenir au contenu précédemment consulté avec l'action de retour.

la transition entre deux volets d&#39;informations.
PopUntilCurrentDestinationChange

Ce comportement supprime la pile "Retour" jusqu'à ce que la destination de navigation actuelle change. Cela s'applique aussi bien aux mises en page à un seul volet qu'à celles à plusieurs volets.

Prenons les exemples suivants :

Que vous utilisiez une mise en page à un seul volet ou à plusieurs volets, appuyer sur le bouton Retour déplace toujours le focus de l'élément de navigation mis en surbrillance vers la destination précédente. Dans notre application de messagerie, cela signifie que l'indication visuelle du volet sélectionné change.

Utilisez cette option lorsque le maintien d'une indication visuelle claire de la navigation actuelle est essentiel pour l'expérience utilisateur.

naviguer entre les volets &quot;Détails&quot; et &quot;Liste&quot;
PopLatest

Cette option ne supprime que la destination la plus récente de la pile "Retour". Utilisez cette option pour le retour en arrière sans ignorer les états intermédiaires.

Une fois ces étapes implémentées, votre code doit ressembler à ce qui suit :

NavigableListDetailPaneScaffold(
    navigator = navigator,
    listPane = {
        AnimatedPane {
            ListContent(
                words = sampleWords,
                selectionState = navigator.currentDestination?.contentKey?.let {
                    SelectionVisibilityState.ShowSelection(it)
                } ?: SelectionVisibilityState.NoSelection,
                onWordClick = { word ->
                    scope.launch {
                        navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, word)
                    }
                },
                animatedVisibilityScope = this@AnimatedPane,
                sharedTransitionScope = this@SharedTransitionLayout
            )
        }
    },
    detailPane = {
        AnimatedPane {
            DetailContent(
                definedWord = navigator.currentDestination?.contentKey,
                animatedVisibilityScope = this@AnimatedPane,
                sharedTransitionScope = this@SharedTransitionLayout,
                onClosePane = {
                    scope.launch {
                        navigator.navigateBack(
                            backNavigationBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange
                        )

                    }
                }
            )
        }
    }