Comprendre et implémenter les principes de base

La navigation décrit la façon dont les utilisateurs se déplacent dans votre application. Ils interagissent avec les éléments de l'interface utilisateur, généralement en appuyant ou en cliquant dessus, et l'application répond en affichant un nouveau contenu. Si l'utilisateur souhaite revenir au contenu précédent, il utilise le geste Retour ou appuie sur le bouton Retour.

Modéliser l'état de navigation

Une façon pratique de modéliser ce comportement consiste à utiliser une pile de contenu. Lorsque l'utilisateur navigue vers l'avant pour accéder à de nouveaux contenus, ceux-ci sont placés au-dessus de la pile. Lorsqu'ils reviennent en arrière à partir de ce contenu, il est retiré de la pile et le contenu précédent s'affiche. En termes de navigation, cette pile est généralement appelée pile "Retour", car elle représente le contenu auquel l'utilisateur peut revenir.

Bouton d'action du clavier virtuel (icône en forme de coche) entouré en rouge.
Figure 1 : Diagramme montrant comment la pile de retour change avec les événements de navigation de l'utilisateur.

Créer une pile de retour

Dans Navigation 3, la pile de retour ne contient pas de contenu. Il contient plutôt des références à du contenu, appelées clés. Les clés peuvent être de n'importe quel type, mais il s'agit généralement de classes de données sérialisables simples. L'utilisation de références plutôt que de contenu présente les avantages suivants :

  • Il est facile de naviguer en appuyant sur les touches de la pile "Retour".
  • Tant que les clés sont sérialisables, la pile "Retour" peut être enregistrée dans un stockage persistant, ce qui lui permet de survivre aux changements de configuration et à l'arrêt du processus. C'est important, car les utilisateurs s'attendent à pouvoir quitter votre application, y revenir plus tard et reprendre là où ils s'étaient arrêtés, avec le même contenu affiché. Pour en savoir plus, consultez Enregistrer votre pile de retour.

Un concept clé de l'API Navigation 3 est que vous êtes propriétaire de la pile arrière. La bibliothèque :

  • S'attend à ce que votre pile de retour soit un List<T> soutenu par un état instantané, où T est le type de votre pile de retour keys. Vous pouvez utiliser Any ou fournir vos propres clés plus fortement typées. Lorsque vous voyez les termes "push" ou "pop", l'implémentation sous-jacente consiste à ajouter ou supprimer des éléments à la fin d'une liste.
  • Observe votre pile "Retour" et reflète son état dans l'UI à l'aide d'un NavDisplay.

L'exemple suivant montre comment créer des clés et une pile de retour, et comment modifier la pile de retour en réponse aux événements de navigation de l'utilisateur :

// Define keys that will identify content
data object ProductList
data class ProductDetail(val id: String)

@Composable
fun MyApp() {

    // Create a back stack, specifying the key the app should start with
    val backStack = remember { mutableStateListOf<Any>(ProductList) }

    // Supply your back stack to a NavDisplay so it can reflect changes in the UI
    // ...more on this below...

    // Push a key onto the back stack (navigate forward), the navigation library will reflect the change in state
    backStack.add(ProductDetail(id = "ABC"))

    // Pop a key off the back stack (navigate back), the navigation library will reflect the change in state
    backStack.removeLastOrNull()
}

Résoudre les clés de contenu

Le contenu est modélisé dans Navigation 3 à l'aide de NavEntry, qui est une classe contenant une fonction composable. Il représente une destination, c'est-à-dire un élément de contenu unique vers lequel l'utilisateur peut avancer et revenir en arrière.

Un NavEntry peut également contenir des métadonnées, c'-à-d. des informations sur le contenu. Ces métadonnées peuvent être lues par des objets conteneurs, comme NavDisplay, pour les aider à décider comment afficher le contenu de NavEntry. Par exemple, les métadonnées peuvent être utilisées pour remplacer les animations par défaut d'un NavEntry spécifique. NavEntry metadata est un mappage de clés String vers des valeurs Any, ce qui permet un stockage polyvalent des données.

Pour convertir un key en NavEntry, créez un fournisseur d'entrées. Il s'agit d'une fonction qui accepte un key et renvoie un NavEntry pour ce key. Il est généralement défini comme paramètre lambda lors de la création d'un NavDisplay.

Il existe deux façons de créer un fournisseur d'entrées : en créant directement une fonction lambda ou en utilisant le DSL entryProvider.

Créer directement une fonction de fournisseur d'entrées

En général, vous créez une fonction Entry Provider à l'aide d'une instruction when, avec une branche pour chacune de vos clés.

entryProvider = { key ->
    when (key) {
        is ProductList -> NavEntry(key) { Text("Product List") }
        is ProductDetail -> NavEntry(
            key,
            metadata = mapOf("extraDataKey" to "extraDataValue")
        ) { Text("Product ${key.id} ") }

        else -> {
            NavEntry(Unit) { Text(text = "Invalid Key: $it") }
        }
    }
}

Utiliser le DSL entryProvider

Le DSL entryProvider peut simplifier votre fonction lambda en vous évitant de tester chacun de vos types de clés et de construire un NavEntry pour chacun d'eux. Pour ce faire, utilisez la fonction de création entryProvider. Il inclut également un comportement de secours par défaut (générant une erreur) si la clé est introuvable.

entryProvider = entryProvider {
    entry<ProductList> { Text("Product List") }
    entry<ProductDetail>(
        metadata = mapOf("extraDataKey" to "extraDataValue")
    ) { key -> Text("Product ${key.id} ") }
}

Notez les points suivants dans l'extrait :

  • entry est utilisé pour définir un NavEntry avec le type et le contenu composable donnés.
  • entry accepte un paramètre metadata pour définir NavEntry.metadata.

Afficher la pile "Retour"

La pile "Retour" représente l'état de navigation de votre application. Chaque fois que la pile "Retour" change, l'UI de l'application doit refléter le nouvel état de la pile "Retour". Dans Navigation 3, un NavDisplay observe votre pile "Retour" et met à jour son UI en conséquence. Construisez-le avec les paramètres suivants :

  • Votre pile de retour : elle doit être de type SnapshotStateList<T>, où T correspond au type de vos clés de pile de retour. Il s'agit d'un List observable qui déclenche la recomposition de NavDisplay lorsqu'il change.
  • Un entryProvider pour convertir les clés de votre pile de retour en objets NavEntry.
  • Vous pouvez également fournir un lambda au paramètre onBack. Celle-ci est appelée lorsque l'utilisateur déclenche un événement Retour.

L'exemple suivant montre comment créer un NavDisplay.

data object Home
data class Product(val id: String)

@Composable
fun NavExample() {

    val backStack = remember { mutableStateListOf<Any>(Home) }

    NavDisplay(
        backStack = backStack,
        onBack = { backStack.removeLastOrNull() },
        entryProvider = { key ->
            when (key) {
                is Home -> NavEntry(key) {
                    ContentGreen("Welcome to Nav3") {
                        Button(onClick = {
                            backStack.add(Product("123"))
                        }) {
                            Text("Click to navigate")
                        }
                    }
                }

                is Product -> NavEntry(key) {
                    ContentBlue("Product ${key.id} ")
                }

                else -> NavEntry(Unit) { Text("Unknown route") }
            }
        }
    )
}

Par défaut, NavDisplay affiche le NavEntry le plus haut de la pile "Retour" dans une mise en page à un seul volet. L'enregistrement suivant montre l'exécution de cette application :

Comportement par défaut de `NavDisplay` avec deux destinations.
Figure 2. Comportement par défaut de NavDisplay avec deux destinations.

Synthèse

Le schéma suivant montre comment les données circulent entre les différents objets de Navigation 3 :

Visualisation du flux de données entre les différents objets de Navigation 3.
Figure 3 : Diagramme montrant comment les données circulent dans différents objets de Navigation 3.
  1. Les événements de navigation déclenchent des modifications. Les clés sont ajoutées ou supprimées de la pile "Retour" en réponse aux interactions utilisateur.

  2. La modification de l'état de la pile de retour déclenche la récupération du contenu. NavDisplay (un composable qui affiche une pile "Retour") observe la pile "Retour". Dans sa configuration par défaut, il affiche l'entrée de pile "Retour" la plus haute dans une mise en page à un seul volet. Lorsque la clé supérieure de la pile de retour change, NavDisplay utilise cette clé pour demander le contenu correspondant au fournisseur d'entrées.

  3. Le fournisseur de la fiche fournit le contenu. Le fournisseur d'entrées est une fonction qui résout une clé en NavEntry. Lorsqu'il reçoit une clé du NavDisplay, le fournisseur d'entrée fournit le NavEntry associé, qui contient à la fois la clé et le contenu.

  4. Le contenu s'affiche. NavDisplay reçoit NavEntry et affiche le contenu.