Ein Listen-Detail-Layout erstellen

Das Listendetail ist ein UI-Muster, das aus einem zweispaltigen Layout besteht, in dem in einer Spalte eine Liste von Elementen und in einer anderen Spalte die Details der aus der Liste ausgewählten Elemente angezeigt werden.

Das Muster ist besonders nützlich für Anwendungen, die detaillierte Informationen zu Elementen großer Sammlungen enthalten, z. B. ein E-Mail-Client mit einer Liste von E-Mails und dem detaillierten Inhalt jeder E-Mail-Nachricht. Listendetails können auch für weniger kritische Pfade verwendet werden, z. B. um App-Einstellungen in eine Liste von Kategorien aufzuteilen, wobei die Einstellungen für jede Kategorie im Detailbereich angezeigt werden.

Ein Detailbereich, der neben der Listenseite angezeigt wird.
Abbildung 1 Wenn der Bildschirm groß genug ist, wird der Detailbereich neben dem Listenbereich angezeigt.
Nachdem ein Element ausgewählt wurde, nimmt der Detailbereich den gesamten Bildschirm ein.
Abbildung 2. Wenn die Bildschirmgröße begrenzt ist, nimmt der Detailbereich (da ein Element ausgewählt wurde) den gesamten Bereich ein.

Listen-Detail-Muster mit NavigableListDetailPaneScaffold implementieren

NavigableListDetailPaneScaffold ist ein Compose-Element, mit dem sich ein Listendetaillayout in Jetpack Compose einfacher implementieren lässt. Es umschließt ListDetailPaneScaffold und fügt eine integrierte Navigation und Animationen für intelligente „Zurück“-Touch-Gesten hinzu.

Ein Listendetail-Scaffold unterstützt bis zu drei Bereiche:

  1. Listenbereich: Hier werden eine Reihe 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 Scaffold 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, der je nach Nutzerinteraktion wechselt.

Abhängigkeiten deklarieren

NavigableListDetailPaneScaffold ist Teil der Material 3-Bibliothek für adaptive Navigation.

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

implementation("androidx.compose.material3.adaptive:adaptive")
implementation("androidx.compose.material3.adaptive:adaptive-layout")
implementation("androidx.compose.material3.adaptive:adaptive-navigation")
implementation 'androidx.compose.material3.adaptive:adaptive'
implementation 'androidx.compose.material3.adaptive:adaptive-layout'
implementation 'androidx.compose.material3.adaptive:adaptive-navigation'
  • adaptive: Low-Level-Bausteine wie HingeInfo und Posture
  • adaptive-layout: Adaptive Layouts wie ListDetailPaneScaffold und SupportingPaneScaffold
  • adaptive-navigation: Composeables für die Navigation innerhalb und zwischen Ansichten sowie adaptive Layouts, die die Navigation standardmäßig 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 die Animationen für die intelligente „Zurück“-Touch-Geste unter Android 15 oder niedriger aktivieren möchten, müssen Sie die Unterstützung für die Geste aktivieren. Wenn Sie die Funktion aktivieren möchten, fügen Sie das Tag android:enableOnBackInvokedCallback="true" dem Tag <application> oder einzelnen <activity>-Tags in Ihrer AndroidManifest.xml-Datei hinzu. Weitere Informationen finden Sie unter Vorhersagende Zurück-Geste aktivieren.

Sobald Ihre App auf Android 16 (API-Level 36) oder höher ausgerichtet ist, ist die Vorhersagefunktion für die Navigation rückwärts 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 ausgewählte Listenelement zu speichern und wiederherzustellen. Verwenden Sie das kotlin-parcelize-Plug-in, um den Code für Sie zu generieren.
  2. Erstellen Sie einen ThreePaneScaffoldNavigator mit rememberListDetailPaneScaffoldNavigator.

Mit diesem Navigationspfad können Sie zwischen der Liste, den Details und den zusätzlichen Bereichen wechseln. Durch die Deklarierung eines generischen Typs überwacht der Navigationspfad auch den Status des Scaffolds, d. h., welche MyItem angezeigt wird. Da dieser Typ teilbar ist, kann der Status vom Navigationssystem gespeichert und wiederhergestellt werden, um Konfigurationsänderungen automatisch zu verarbeiten.

  1. Übergeben Sie den Navigationspfad an das NavigableListDetailPaneScaffold-Komposit.

  2. Stellen Sie die Implementierung des Listenbereichs für die NavigableListDetailPaneScaffold bereit. Mit AnimatedPane können Sie die Standard-Fensteranimationen während der Navigation anwenden. Gehen Sie dann mit ThreePaneScaffoldNavigator zum Detailbereich ListDetailPaneScaffoldRole.Detail und rufen Sie den übergebenen Artikel auf.

  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 gewechselt ist, einschließlich der darin angezeigten Inhalte. Die Property contentKey hat denselben Typ wie im ursprünglichen Aufruf angegeben, sodass du auf alle Daten zugreifen kannst, die du anzeigen möchtest.

  1. Optional können Sie das defaultBackBehavior in NavigableListDetailPaneScaffold ändern. Standardmäßig verwendet NavigableListDetailPaneScaffold PopUntilScaffoldValueChange für defaultBackBehavior.

Wenn Ihre App ein anderes Navigationsmuster für die Rückwärtsnavigation 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.

Dabei liegt der Schwerpunkt auf Änderungen an der gesamten Layoutstruktur. Bei einer Einrichtung mit mehreren Ansichten ändert sich die zugrunde liegende Layoutstruktur nicht, wenn Sie den E-Mail-Inhalt im Detailbereich ändern. Daher wird die App oder der aktuelle Navigationsgraph möglicherweise über die Schaltfläche „Zurück“ geschlossen, da es im aktuellen Kontext keine Layoutänderung gibt, zu der zurückgekehrt werden kann. Bei einem einspaltigen Layout werden beim Drücken der Rückwärtstaste Inhaltsänderungen in der Detailansicht übersprungen und Sie kehren zur Listenansicht zurück, da dies eine deutliche Layoutänderung darstellt.

Betrachten Sie hierzu folgende Beispiele:

  • Mehrere Bereiche:Im Detailbereich wird eine E-Mail (Element 1) angezeigt. Wenn Sie auf eine andere E-Mail klicken (Punkt 2), wird der Detailbereich aktualisiert, aber die Listen- und Detailbereiche bleiben sichtbar. Wenn Sie auf „Zurück“ drücken, wird möglicherweise die App oder der aktuelle Navigationsfluss geschlossen.
  • Ein-Spalten-Ansicht:Sie sehen sich Element 1 und dann Element 2 an. Wenn Sie die Rückwärtstaste drücken, kehren Sie direkt zum Bereich mit der E-Mail-Liste zurück.

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

Änderung des Navigationswerts.
PopUntilContentChange

Bei diesem Verhalten werden die angezeigten Inhalte priorisiert. Wenn Sie sich Element 1 und dann Element 2 ansehen, kehren Sie unabhängig vom Layout durch Drücken der Rückwärtstaste zu Element 1 zurück.

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“ klicken, wird der Detailbereich auf Element 1 zurückgesetzt.
  • Einzeiliger Bereich:Dieselben Inhalte werden wiederhergestellt.

Verwenden Sie diese Option, wenn Nutzer mit der Schaltfläche „Zurück“ zu den zuvor angesehenen Inhalten zurückkehren möchten.

den Übergang zwischen zwei Detailbereichen
PopUntilCurrentDestinationChange

Dabei wird der Rückstapel so lange angezeigt, bis sich das aktuelle Navigationsziel ändert. Das gilt sowohl für Layouts mit einer als auch mit mehreren Ansichten.

Betrachten Sie hierzu folgende Beispiele:

Unabhängig davon, ob Sie sich in einem ein- oder mehrspaltigen Layout befinden, wird der Fokus durch Drücken der Schaltfläche „Zurück“ immer vom hervorgehobenen Navigationselement auf das vorherige Ziel verschoben. In unserer E-Mail-App bedeutet das, dass sich die visuelle Anzeige des ausgewählten Bereichs verschiebt.

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

Zwischen Detail- und Listenbereich wechseln
PopLatest

Mit 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.

Nach diesen Schritten 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)
            }
        }
    },
)