Comprendre et implémenter les principes de base

La navigation décrit la façon dont les utilisateurs se déplacent dans votre application. Les utilisateurs interagissent avec les éléments d'interface utilisateur, généralement en appuyant dessus ou en cliquant dessus, et l'application répond en affichant de nouveaux contenus. 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

Un moyen pratique de modéliser ce comportement consiste à utiliser une pile de contenus. Lorsque l'utilisateur avance vers un nouveau contenu, celui-ci est placé en haut de la pile. Lorsqu'il revient 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.

Un bouton d'action du clavier logiciel (une icône en forme de coche) entouré en rouge.
Figure 1 Schéma montrant comment la pile "Retour" change avec les événements de navigation de l'utilisateur.

Créer une pile "Retour"

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

  • La navigation est simple en ajoutant des touches à la pile "Retour".
  • Tant que les clés sont sérialisables, la pile "Retour" peut être enregistrée dans un espace de stockage persistant, ce qui lui permet de survivre aux modifications de configuration et à l'arrêt du processus. Cela est important, car les utilisateurs s'attendent à 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 la pile "Retour".

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

  • Attend que votre pile "Retour" soit un List<T> basé sur l'état de l'instantané, où T est le type de votre pile "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 "Retour", et modifier la pile "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()
}

Associer des clés à du 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 auquel l'utilisateur peut accéder et en revenir.

Un NavEntry peut également contenir des métadonnées, c'est-à-dire des informations sur le contenu. Ces métadonnées peuvent être lues par des objets de conteneur, 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. metadata NavEntry est un mappage des clés String sur les valeurs Any, ce qui permet un stockage de données polyvalent.

Pour convertir un key en NavEntry, créez un entryProvider. 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 un paramètre lambda lors de la création d'un NavDisplay.

Il existe deux façons de créer un entryProvider : en créant directement une fonction lambda ou à l'aide du DSL entryProvider.

Créer directement une fonction entryProvider

Vous créez généralement une fonction entryProvider à 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 évitant d'avoir à effectuer des tests pour chacun de vos types de clés et de créer un NavEntry pour chacun d'eux. Pour ce faire, utilisez la fonction de compilateur entryProvider. Il inclut également le comportement de remplacement par défaut (génération d'une erreur) si la clé n'est pas trouvée.

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 permet de 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. Créez-le avec les paramètres suivants:

  • Votre pile "Retour" doit être de type SnapshotStateList<T>, où T est le type de vos clés de pile "Retour". Il s'agit d'un List observable afin qu'il déclenche la recomposition de NavDisplay lorsqu'il change.
  • Un entryProvider pour convertir les clés de votre pile "Retour" en NavEntry.
  • Vous pouvez également fournir un lambda au paramètre onBack. Cette méthode 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 élevé de la pile "Retour" dans une mise en page à un seul volet. L'enregistrement suivant montre cette application en cours d'exécution:

Comportement par défaut de &quot;NavDisplay&quot; 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 Schéma illustrant le flux de données dans différents objets dans Navigation 3.
  1. Les événements de navigation déclenchent les modifications. Les clés sont ajoutées ou supprimées de la pile "Retour" en réponse aux interactions utilisateur.

  2. Un changement d'état de la pile "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 la pile "Retour" la plus élevée dans une mise en page à un seul volet. Lorsque la touche supérieure de la pile "Retour" change, NavDisplay utilise cette touche pour demander le contenu correspondant au fournisseur de saisie.

  3. Le fournisseur d'entrée fournit le contenu. Le fournisseur d'entrée est une fonction qui résout une clé en NavEntry. Lorsqu'il reçoit une clé de la part de 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.