Ein Listen-Detail-Layout erstellen

„Liste/Details“ ist ein UI-Muster, das aus einem Layout mit zwei Bereichen besteht. In einem Bereich wird eine Liste mit Elementen angezeigt, im anderen die Details der Elemente, die aus der Liste ausgewählt wurden.

Das Muster ist besonders nützlich für Anwendungen, die detaillierte Informationen zu Elementen großer Sammlungen liefern, z. B. ein E‑Mail-Client mit einer Liste von E‑Mails und dem detaillierten Inhalt jeder E‑Mail. Die Listendetailansicht kann auch für weniger kritische Pfade verwendet werden, z. B. zum Aufteilen von App-Einstellungen in eine Liste von Kategorien mit den Einstellungen für jede Kategorie im Detailbereich.

Ein Detailbereich, der neben der Listenseite angezeigt wird.
Abbildung 1: Wenn genügend Bildschirmplatz vorhanden ist, wird der Detailbereich neben dem Listenbereich angezeigt.
Nachdem ein Element ausgewählt wurde, wird der Detailbereich auf dem gesamten Bildschirm angezeigt.
Abbildung 2. Wenn die Bildschirmgröße begrenzt ist, nimmt der Detailbereich (nachdem ein Element ausgewählt wurde) den gesamten Platz ein.

Implementieren des List-Detail-Musters mit NavigableListDetailPaneScaffold

NavigableListDetailPaneScaffold ist eine Composable-Funktion, die die Implementierung eines Listen-/Detail-Layouts in Jetpack Compose vereinfacht. Es umschließt ListDetailPaneScaffold und fügt integrierte Navigation und Animationen für die intelligente „Zurück“-Geste hinzu.

Ein Listendetail-Gerüst unterstützt bis zu drei Bereiche:

  1. Listenbereich: Hier wird eine Sammlung von Elementen angezeigt.
  2. Detailbereich: Hier werden die Details eines ausgewählten Elements angezeigt.
  3. Zusätzlicher Bereich (optional): Bietet bei Bedarf zusätzlichen Kontext.

Das Gerüst passt sich an die Fenstergröße an:

  • In großen Fenstern werden die Listen- und Detailbereiche nebeneinander angezeigt.
  • In kleinen Fenstern ist jeweils nur ein Bereich sichtbar. Die Bereiche werden gewechselt, wenn Nutzer navigieren.

Abhängigkeiten deklarieren

NavigableListDetailPaneScaffold ist Teil der adaptiven Navigationsbibliothek für Material 3.

Fügen Sie der Datei build.gradle Ihrer App oder Ihres Moduls die folgenden drei zugehörigen Abhängigkeiten hinzu:

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'
  • adaptiv: Low-Level-Bausteine wie HingeInfo und Posture
  • adaptive-layout: Adaptive Layouts wie ListDetailPaneScaffold und SupportingPaneScaffold
  • adaptive-navigation: Composables für die Navigation innerhalb und zwischen Bereichen sowie adaptive Layouts, die standardmäßig die Navigation unterstützen, z. B. NavigableListDetailPaneScaffold und NavigableSupportingPaneScaffold

Ihr Projekt muss compose-material3-adaptive Version 1.1.0-beta1 oder höher enthalten.

Intelligente „Zurück“-Touch-Geste aktivieren

Wenn Sie Animationen für die intelligente „Zurück“-Touchgeste in Android 15 oder niedriger aktivieren möchten, müssen Sie die Unterstützung für die intelligente „Zurück“-Touchgeste aktivieren. Fügen Sie dazu android:enableOnBackInvokedCallback="true" dem Tag <application> oder einzelnen <activity>-Tags in Ihrer AndroidManifest.xml-Datei hinzu. Weitere Informationen finden Sie unter Predictive Back-Geste aktivieren.

Sobald Ihre App auf Android 16 (API‑Level 36) oder höher ausgerichtet ist, ist die Funktion „Vorhersagende Zurück-Geste“ standardmäßig aktiviert.

Grundlegende Nutzung

Implementieren Sie NavigableListDetailPaneScaffold so:

  1. Verwenden Sie eine Klasse, die die ausgewählten Inhalte darstellt. Verwenden Sie die Klasse Parcelable, um das Speichern und Wiederherstellen des ausgewählten Listenelements zu unterstützen. Verwenden Sie das kotlin-parcelize-Plug-in, um den Code generieren zu lassen.
  2. Erstellen Sie eine ThreePaneScaffoldNavigator mit rememberListDetailPaneScaffoldNavigator.

Mit diesem Navigator können Sie zwischen der Liste, dem Detailbereich und den zusätzlichen Bereichen wechseln. Durch die Deklaration eines generischen Typs verfolgt der Navigator auch den Status des Gerüsts (d. h. welche MyItem angezeigt wird). Da dieser Typ parcelable ist, kann der Status vom Navigator gespeichert und wiederhergestellt werden, um Konfigurationsänderungen automatisch zu verarbeiten.

  1. Übergeben Sie den Navigator an die zusammensetzbare Funktion NavigableListDetailPaneScaffold.

  2. Stellen Sie die Implementierung des Listenbereichs für NavigableListDetailPaneScaffold bereit. Verwenden Sie AnimatedPane, um die Standardanimationen für Bereiche während der Navigation anzuwenden. Verwenden Sie dann ThreePaneScaffoldNavigator, um zum Detailbereich ListDetailPaneScaffoldRole.Detail zu wechseln und das übergebene Element anzuzeigen.

  3. Fügen Sie die Implementierung des Detailbereichs in NavigableListDetailPaneScaffold ein.

Wenn die Navigation abgeschlossen ist, enthält currentDestination den Bereich, zu dem Ihre App navigiert ist, einschließlich der im Bereich angezeigten Inhalte. Die contentKey-Property hat denselben Typ wie im ursprünglichen Aufruf angegeben. Sie können also auf alle Daten zugreifen, die Sie anzeigen müssen.

  1. Ändern Sie optional defaultBackBehavior in NavigableListDetailPaneScaffold. Standardmäßig verwendet NavigableListDetailPaneScaffold PopUntilScaffoldValueChange für defaultBackBehavior.

Wenn Ihre App ein anderes Muster für die Zurück-Navigation erfordert, können Sie dieses Verhalten überschreiben, indem Sie eine andere BackNavigationBehavior-Option angeben.

Optionen für BackNavigationBehavior

Im folgenden Abschnitt wird das Beispiel einer E‑Mail-App mit einer Liste von E‑Mails in einem Bereich und einer Detailansicht im anderen verwendet.

Dieses Verhalten bezieht sich auf Änderungen an der allgemeinen Layoutstruktur. Wenn Sie in einer Einrichtung mit mehreren Bereichen den E-Mail-Inhalt im Detailbereich ändern, wird die zugrunde liegende Layoutstruktur nicht geändert. Daher kann es sein, dass die App oder der aktuelle Navigationsgraph durch Drücken der Zurück-Schaltfläche beendet wird, da im aktuellen Kontext keine Layoutänderung rückgängig gemacht werden kann. In einem Layout mit einem Bereich werden durch Drücken der Zurück-Taste Inhaltsänderungen in der Detailansicht übersprungen und zur Listenansicht zurückgekehrt, da dies eine deutliche Layoutänderung darstellt.

Betrachten Sie hierzu folgende Beispiele:

  • Mehrspaltig:Sie sehen sich eine E‑Mail (Element 1) im Detailbereich an. Wenn Sie auf eine andere E‑Mail (Punkt 2) klicken, wird der Detailbereich aktualisiert, aber die Listen- und Detailbereiche bleiben sichtbar. Durch Drücken der Zurück-Taste wird die App oder der aktuelle Navigationsvorgang möglicherweise beendet.
  • Einzelbereich:Sie sehen zuerst Element 1 und dann Element 2. Wenn Sie auf „Zurück“ tippen, kehren Sie direkt zum Bereich mit der E‑Mail-Liste zurück.

Verwenden Sie diese Option, wenn Nutzer bei jeder Zurück-Aktion deutliche Layoutübergänge sehen sollen.

Änderung des Navigationswerts.
PopUntilContentChange

So wird der angezeigte Inhalt priorisiert. Wenn Sie sich zuerst Artikel 1 und dann Artikel 2 ansehen, gelangen Sie durch Drücken der Zurück-Taste wieder zu Artikel 1, unabhängig vom Layout.

Betrachten Sie hierzu folgende Beispiele:

  • Mehrere Bereiche:Sie sehen sich Element 1 im Detailbereich an und klicken dann in der Liste auf Element 2. Der Detailbereich wird aktualisiert. Wenn Sie auf „Zurück“ drücken, wird der Detailbereich auf Element 1 zurückgesetzt.
  • Einzelnes Feld:Es kommt zur selben Inhaltsreversion.

Verwenden Sie diese Option, wenn der Nutzer erwartet, mit der Zurück-Aktion zum zuvor angesehenen Inhalt zurückzukehren.

der Übergang zwischen zwei Detailbereichen
PopUntilCurrentDestinationChange

Dadurch wird der Backstack so lange geleert, bis sich das aktuelle Navigationsziel ändert. Dies gilt gleichermaßen für Layouts mit einem und mehreren Bereichen.

Betrachten Sie hierzu folgende Beispiele:

Unabhängig davon, ob Sie sich in einem Layout mit einem oder mehreren Bereichen befinden, wird durch Drücken der Zurück-Taste der Fokus immer vom hervorgehobenen Navigationselement zum vorherigen Ziel verschoben. In unserer E‑Mail-App bedeutet das, dass sich die visuelle Darstellung des ausgewählten Bereichs ändert.

Verwenden Sie diese Option, wenn eine klare visuelle Anzeige der aktuellen Navigation für die Nutzererfahrung entscheidend ist.

zwischen Detail- und Listenbereich wechseln
PopLatest

Bei dieser Option wird nur das letzte Ziel aus dem Backstack entfernt. Verwenden Sie diese Option für die Rückwärtsnavigation, ohne Zwischenzustände zu überspringen.

Nachdem Sie diese Schritte ausgeführt haben, sollte Ihr Code in etwa so aussehen:

val scaffoldNavigator = rememberListDetailPaneScaffoldNavigator<MyItem>()
val scope = rememberCoroutineScope()

NavigableListDetailPaneScaffold(
    navigator = scaffoldNavigator,
    listPane = {
        AnimatedPane {
            MyList(
                onItemClick = { item ->
                    // Navigate to the detail pane with the passed item
                    scope.launch {
                        scaffoldNavigator.navigateTo(
                            ListDetailPaneScaffoldRole.Detail,
                            item
                        )
                    }
                },
            )
        }
    },
    detailPane = {
        AnimatedPane {
            // Show the detail pane content if selected item is available
            scaffoldNavigator.currentDestination?.contentKey?.let {
                MyDetails(it)
            }
        }
    },
)