Die Navigation beschreibt, wie sich Nutzer in Ihrer App bewegen. Nutzer interagieren mit UI-Elementen, in der Regel durch Tippen oder Klicken, und die App reagiert darauf, indem sie neue Inhalte anzeigt. Wenn der Nutzer zum vorherigen Inhalt zurückkehren möchte, verwendet er die Touch-Geste „Zurück“ oder tippt auf die Schaltfläche „Zurück“.
Navigationsstatus modellieren
Eine praktische Möglichkeit, dieses Verhalten zu modellieren, ist ein Stapel von Inhalten. Wenn der Nutzer vorwärts zu neuen Inhalten navigiert, werden diese oben auf den Stapel gelegt. Wenn sie zurück zu diesem Inhalt gehen, wird er aus dem Stapel entfernt und der vorherige Inhalt wird angezeigt. In der Navigation wird dieser Stapel normalerweise als Backstack bezeichnet, da er die Inhalte darstellt, zu denen der Nutzer zurückkehren kann.
Backstack erstellen
In Navigation 3 enthält der Backstack keinen Inhalt. Stattdessen enthält sie Verweise auf Inhalte, die als Schlüssel bezeichnet werden. Schlüssel können einen beliebigen Typ haben, sind aber in der Regel einfache, serialisierbare Datenklassen. Die Verwendung von Referenzen anstelle von Inhalten hat folgende Vorteile:
- Die Navigation ist einfach, da Tasten auf den Backstack gelegt werden.
- Solange die Schlüssel serialisierbar sind, kann der Backstack im persistenten Speicher gespeichert werden, sodass er Konfigurationsänderungen und das Beenden des Prozesses übersteht. Das ist wichtig, weil Nutzer erwarten, dass sie Ihre App verlassen, später wieder aufrufen und dort weitermachen können, wo sie aufgehört haben, wobei dieselben Inhalte angezeigt werden. Weitere Informationen finden Sie unter Backstack speichern.
Ein wichtiges Konzept in der Navigation 3-API ist, dass Sie den Backstack besitzen. Die Bibliothek:
- Erwartet, dass Ihr Backstack ein Snapshot-State-basiertes
List<T>ist, wobeiTder Typ Ihres Backstack-keysist. Sie könnenAnyverwenden oder eigene, stärker typisierte Schlüssel bereitstellen. Wenn Sie die Begriffe „push“ oder „pop“ sehen, werden Elemente in der zugrunde liegenden Implementierung am Ende einer Liste hinzugefügt oder entfernt. - Beobachtet den Backstack und spiegelt seinen Status in der Benutzeroberfläche mithilfe eines
NavDisplaywider.
Im folgenden Beispiel wird gezeigt, wie Sie Schlüssel und einen Backstack erstellen und den Backstack als Reaktion auf Navigationsereignisse von Nutzern ändern:
// 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() }
Schlüssel für Inhalte auflösen
In Navigation 3 wird Inhalt mit NavEntry modelliert. Das ist eine Klasse, die eine zusammensetzbare Funktion enthält. Sie stellt ein Ziel dar – einen einzelnen Inhalt, zu dem der Nutzer vorwärts und zurück navigieren kann.
Eine NavEntry kann auch Metadaten enthalten, also Informationen zum Inhalt. Diese Metadaten können von Containerobjekten wie NavDisplay gelesen werden, um zu entscheiden, wie die Inhalte des NavEntry angezeigt werden sollen. Mit Metadaten lassen sich beispielsweise die Standardanimationen für ein bestimmtes NavEntry überschreiben. NavEntry
metadata ist eine Zuordnung von String-Schlüsseln zu Any-Werten, die eine vielseitige Datenspeicherung ermöglicht.
Wenn Sie eine key in eine NavEntry umwandeln möchten, erstellen Sie einen Entry Provider. Diese Funktion akzeptiert eine key und gibt eine NavEntry für diese key zurück. Er wird in der Regel als Lambdaparameter beim Erstellen eines NavDisplay definiert.
Es gibt zwei Möglichkeiten, einen Entry Provider zu erstellen: entweder direkt mit einer Lambda-Funktion oder mit der entryProvider-DSL.
Funktion für den Eintragsanbieter direkt erstellen
Normalerweise erstellen Sie eine Entry Provider-Funktion mit einer when-Anweisung mit einem Zweig für jeden Ihrer Schlüssel.
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") } } } }
entryProvider-DSL verwenden
Mit der entryProvider-DSL können Sie Ihre Lambda-Funktion vereinfachen, da Sie nicht für jeden Ihrer Schlüsseltypen einen Test durchführen und für jeden einen NavEntry erstellen müssen.
Verwenden Sie dazu die Builder-Funktion entryProvider. Außerdem ist ein Standard-Fallbackverhalten (Auslösen eines Fehlers) enthalten, wenn der Schlüssel nicht gefunden wird.
entryProvider = entryProvider { entry<ProductList> { Text("Product List") } entry<ProductDetail>( metadata = mapOf("extraDataKey" to "extraDataValue") ) { key -> Text("Product ${key.id} ") } }
Beachten Sie Folgendes im Snippet:
- Mit
entrywird einNavEntrymit dem angegebenen Typ und zusammensetzbaren Inhalt definiert. entryakzeptiert einenmetadata-Parameter zum Festlegen vonNavEntry.metadata.
Backstack anzeigen
Der Backstack stellt den Navigationsstatus Ihrer App dar. Immer wenn sich der Backstack ändert, sollte die App-Benutzeroberfläche den neuen Backstack-Status widerspiegeln. In Navigation 3 beobachtet ein NavDisplay den Backstack und aktualisiert die Benutzeroberfläche entsprechend. Erstellen Sie sie mit den folgenden Parametern:
- Ihr Backstack – dieser sollte vom Typ
SnapshotStateList<T>sein, wobeiTder Typ Ihrer Backstack-Schlüssel ist. Es ist ein beobachtbaresList, sodass bei einer Änderung die Neuzusammensetzung vonNavDisplayausgelöst wird. - Ein
entryProviderzum Konvertieren der Schlüssel in Ihrem Backstack inNavEntry-Objekte. - Optional können Sie dem Parameter
onBackeine Lambda-Funktion übergeben. Diese Methode wird aufgerufen, wenn der Nutzer ein Zurück-Ereignis auslöst.
Das folgende Beispiel zeigt, wie ein NavDisplay erstellt wird.
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") } } } ) }
Standardmäßig wird im NavDisplay das oberste NavEntry im Backstack in einem Layout mit einem Bereich angezeigt. Die folgende Aufnahme zeigt die Ausführung dieser App:
NavDisplay-Standardverhalten mit zwei Zielen.Zusammenfassung
Das folgende Diagramm zeigt, wie Daten zwischen den verschiedenen Objekten in Navigation 3 fließen:
Navigationsereignisse lösen Änderungen aus: Schlüssel werden als Reaktion auf Nutzerinteraktionen dem Backstack hinzugefügt oder daraus entfernt.
Änderung des Backstack-Status löst das Abrufen von Inhalten aus: Die
NavDisplay-Funktion (eine zusammensetzbare Funktion, die einen Backstack rendert) beobachtet den Backstack. In der Standardkonfiguration wird der oberste Backstack-Eintrag in einem Layout mit einem einzelnen Bereich angezeigt. Wenn sich der oberste Schlüssel im Backstack ändert, verwendetNavDisplaydiesen Schlüssel, um die entsprechenden Inhalte vom Eintragsanbieter anzufordern.Eintragsanbieter stellt Inhalte bereit: Der Eintragsanbieter ist eine Funktion, die einen Schlüssel in ein
NavEntryauflöst. Nachdem der Eintraganbieter einen Schlüssel vonNavDisplayerhalten hat, stellt er die zugehörigeNavEntrybereit, die sowohl den Schlüssel als auch die Inhalte enthält.Inhalte werden angezeigt: Das
NavDisplayempfängt dasNavEntryund zeigt den Inhalt an.