Crea un layout elenco-dettagli

List-detail è un pattern UI costituito da un layout a due riquadri in cui un riquadro presenta un elenco di elementi e un altro riquadro con i dettagli degli elementi selezionati dall'elenco.

Il pattern è particolarmente utile per le applicazioni che forniscono informazioni su elementi di grandi raccolte, ad esempio un client di posta che contiene un elenco di email e i contenuti dettagliati di ciascun messaggio. L'elenco dettagliato può essere utilizzato anche per percorsi meno critici come la divisione dell'app preferenze in un elenco di categorie con le preferenze per ogni categoria in nel riquadro dei dettagli.

Implementa pattern UI con ListDetailPaneScaffold

ListDetailPaneScaffold è un componibile che semplifica l'implementazione di il pattern dell'elenco dei dettagli nell'app. Uno scaffold elenco dettagli può essere composto da un massimo di tre riquadri: un riquadro dell'elenco, un riquadro dei dettagli e un riquadro aggiuntivo facoltativo. La lo scaffold gestisce i calcoli dello spazio sullo schermo. Quando le dimensioni dello schermo sono sufficienti se disponibile, il riquadro dei dettagli viene visualizzato accanto al riquadro dell'elenco. Su schermo piccolo dimensioni, lo scaffold passa automaticamente alla visualizzazione dell'elenco o riquadro dei dettagli a schermo intero.

Un riquadro dei dettagli visualizzato accanto alla pagina dell'elenco.
Figura 1. Quando sono disponibili dimensioni dello schermo sufficienti, i dettagli viene mostrato accanto al riquadro dell'elenco.
Dopo aver selezionato un elemento, il riquadro dei dettagli occupa l'intero schermo.
Figura 2. Quando le dimensioni dello schermo sono limitate, il riquadro dei dettagli (dato che un elemento è stato selezionato). occupa tutto lo spazio.

Dichiara le dipendenze

ListDetailPaneScaffold fa parte del layout adattivo di Material 3 libreria di Google Cloud.

La tua app deve includere dipendenze per tre librerie Material 3 correlate:

  • Adattiva: componenti di base di basso livello come HingeInfo e Posture
  • adaptive-layout: layout adattivi come ListDetailPaneScaffold e SupportingPaneScaffold
    • navigazione adattiva: elementi componibili per la navigazione all'interno di tra i riquadri

Aggiungi le dipendenze al file build.gradle della tua app o del tuo modulo:

Kotlin


implementation("androidx.compose.material3.adaptive:adaptive:1.0.0-alpha12")
implementation("androidx.compose.material3.adaptive:adaptive-layout:1.0.0-alpha12")
implementation("androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-alpha12")

Alla moda


implementation 'androidx.compose.material3.adaptive:adaptive:1.0.0-alpha12'
implementation 'androidx.compose.material3.adaptive:adaptive-layout:1.0.0-alpha12'
implementation 'androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-alpha12'

Utilizzo di base

Implementa ListDetailPaneScaffold nel seguente modo:

  1. Utilizza una classe che rappresenti i contenuti da selezionare. Questo corso dovrebbe essere Parcelable per supportare il salvataggio e ripristinando l'elemento dell'elenco selezionato. Utilizza il comando kotlin-parcelize plug-in per generare il codice per te.

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

  2. Crea un ThreePaneScaffoldNavigator con rememberListDetailPaneScaffoldNavigator e aggiungi BackHandler. Questo il navigatore viene utilizzato per spostarsi tra l'elenco, i dettagli e i riquadri aggiuntivi. Di dichiarando un tipo generico, il navigatore monitora anche lo stato del scaffold (ovvero, MyItem viene visualizzato). Poiché questo tipo è "parcelable", lo stato può essere salvato e ripristinato dal navigatore per e gestire automaticamente le modifiche alla configurazione. La BackHandler supporta la navigazione indietro utilizzando il gesto Indietro di sistema o . Il comportamento previsto del pulsante Indietro per ListDetailPaneScaffold dipende dalle dimensioni della finestra e dallo scaffold attuale valore. Se ListDetailPaneScaffold è in grado di supportare il recupero attuale, il valore canNavigateBack() è true e viene attivato BackHandler.

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

  3. Passa il scaffoldState dal navigator al ListDetailPaneScaffold componibile.

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

  4. Fornisci l'implementazione del riquadro elenco a ListDetailPaneScaffold. Utilizza le funzionalità di AnimatedPane per applicare le animazioni predefinite dei riquadri durante la navigazione. Quindi utilizza ThreePaneScaffoldNavigator per accedere al riquadro dei dettagli, ListDetailPaneScaffoldRole.Detail e visualizzare l'elemento passato.

    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. Includi l'implementazione del riquadro dei dettagli in ListDetailPaneScaffold. Al termine della navigazione, currentDestination contiene il riquadro raggiunto dall'app, inclusi i contenuti visualizzati nel riquadro. La La proprietà content è dello stesso tipo specificato nella chiamata di promemoria originale (MyItem in questo esempio), per poter accedere alla proprietà anche per qualsiasi dato che devi visualizzare.

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

Dopo aver implementato i passaggi precedenti, il codice dovrebbe essere simile al seguente:

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)
            }
        }
    },
)