Ein Listen-Detail-Layout erstellen

„List-Detail“ ist ein UI-Muster, das aus einem Dual-Pane-Layout besteht, bei dem ein Bereich zeigt eine Liste mit Elementen an, während ein weiterer Bereich die Details zu den ausgewählten Elementen enthält. aus der Liste aus.

Das Muster ist besonders nützlich für Anwendungen, die detaillierte Informationen zu Elementen großer Sammlungen, z. B. zu E-Mail-Clients mit einer Liste von E-Mails und dem detaillierten Inhalt jeder E-Mail-Nachricht. Die Funktion „Listendetails“ kann auch für weniger wichtige Pfade wie das Unterteilen von Apps verwendet werden. in eine Liste von Kategorien mit den Einstellungen für jede Kategorie in Detailbereich.

UI-Muster mit ListDetailPaneScaffold implementieren

ListDetailPaneScaffold ist eine zusammensetzbare Funktion, die die Implementierung von das Listen-Detail-Muster in deiner App. Ein Gerüst mit Listendetails kann bis zu einen Listenbereich, einen Detailbereich und einen optionalen zusätzlichen Bereich. Die die Bildschirmflächenberechnungen. Bei ausreichender Bildschirmgröße verfügbar ist, wird der Detailbereich neben dem Listenbereich angezeigt. Auf einem kleinen Display wechselt das Gerüst automatisch zur Anzeige der Liste oder Detailbereich im Vollbildmodus.

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. Bei eingeschränkter Bildschirmgröße: Detailbereich (da ein Element ausgewählt wurde) die den gesamten Raum einnimmt.

Abhängigkeiten deklarieren

ListDetailPaneScaffold ist Teil des Adaptiven Material 3-Layouts .

Fügen Sie die folgenden drei zusammengehörigen Abhängigkeiten in die Datei build.gradle Ihres App oder Modul:

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'
  • 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 Bereichen

Grundlegende Nutzung

Implementieren Sie ListDetailPaneScaffold so:

  1. Verwenden Sie eine Klasse, die den auszuwählenden Inhalt darstellt. Diese Klasse sollte Parcelable sein, um das Speichern und Wiederherstellen des ausgewählten Listenelements zu unterstützen. Verwenden Sie das kotlin-parcelize-Plug-in, um den Code für Sie zu generieren.

    @Parcelize
    class MyItem(val id: Int) : Parcelable

  2. Erstellen Sie ein ThreePaneScaffoldNavigator mit rememberListDetailPaneScaffoldNavigator und füge BackHandler hinzu. Mit diesem Navigationspfad können Sie zwischen der Liste, den Details und den zusätzlichen Bereichen wechseln. Von gibt der Navigator einen generischen Typ an, Scaffold (das heißt, MyItem wird angezeigt). Da dieser Typ teilbar ist, kann der Status vom Navigationssystem gespeichert und wiederhergestellt werden, um Konfigurationsänderungen automatisch zu verarbeiten. Mit BackHandler können Sie mit der Systemgeste oder -schaltfläche zurückgehen. Das erwartete Verhalten der Zurück-Schaltfläche für eine ListDetailPaneScaffold hängt von der Fenstergröße und dem aktuellen Gerüst ab Wert. Wenn der ListDetailPaneScaffold den Rückweg zum aktuellen Status unterstützt, ist canNavigateBack() true und die BackHandler wird aktiviert.

    val navigator = rememberListDetailPaneScaffoldNavigator<MyItem>()
    
    BackHandler(navigator.canNavigateBack()) {
        navigator.navigateBack()
    }

  3. Übergeben Sie die scaffoldState von der navigator an die ListDetailPaneScaffold zusammensetzbar.

    ListDetailPaneScaffold(
        directive = navigator.scaffoldDirective,
        value = navigator.scaffoldValue,
        // ...
    )

  4. Stellen Sie Ihre Listenbereich-Implementierung für den ListDetailPaneScaffold bereit. Verwenden Sie AnimatedPane um die standardmäßigen Fensteranimationen während der Navigation anzuwenden. Verwenden Sie dann ThreePaneScaffoldNavigator, um zum Detailbereich zu wechseln, ListDetailPaneScaffoldRole.Detail und rufen Sie das übergebene Element auf.

    ListDetailPaneScaffold(
        directive = navigator.scaffoldDirective,
        value = navigator.scaffoldValue,
        listPane = {
            AnimatedPane {
                MyList(
                    onItemClick = { item ->
                        // Navigate to the detail pane with the passed item
                        navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item)
                    }
                )
            }
        },
        // ...
    )

  5. Fügen Sie die Implementierung des Detailbereichs in ListDetailPaneScaffold ein. Wenn die Navigation abgeschlossen ist, enthält currentDestination den Bereich, aufgerufen wurde, einschließlich des in dem Bereich angezeigten Inhalts. Die Property content hat denselben Typ wie im ursprünglichen remember-Aufruf angegeben (MyItem in diesem Beispiel). Sie können also auch auf die Property für alle Daten zugreifen, die angezeigt werden sollen.

    ListDetailPaneScaffold(
        directive = navigator.scaffoldDirective,
        value = navigator.scaffoldValue,
        listPane =
        // ...
        detailPane = {
            AnimatedPane {
                navigator.currentDestination?.content?.let {
                    MyDetails(it)
                }
            }
        },
    )

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

val navigator = rememberListDetailPaneScaffoldNavigator<MyItem>()

BackHandler(navigator.canNavigateBack()) {
    navigator.navigateBack()
}

ListDetailPaneScaffold(
    directive = navigator.scaffoldDirective,
    value = navigator.scaffoldValue,
    listPane = {
        AnimatedPane {
            MyList(
                onItemClick = { item ->
                    // Navigate to the detail pane with the passed item
                    navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item)
                },
            )
        }
    },
    detailPane = {
        AnimatedPane {
            // Show the detail pane content if selected item is available
            navigator.currentDestination?.content?.let {
                MyDetails(it)
            }
        }
    },
)