Crea un layout elenco-dettagli

Elenco-dettaglio è un pattern UI costituito da un layout a doppio riquadro in cui un riquadro presenta un elenco di elementi e un altro riquadro mostra i dettagli degli elementi selezionati dall'elenco.

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

Implementa il pattern UI con ListDetailPaneScaffold

ListDetailPaneScaffold è un elemento componibile che semplifica l'implementazione del pattern dei dettagli dell'elenco nella tua app. Un'impalcatura dei dettagli dell'elenco può essere costituita da massimo tre riquadri: un riquadro elenco, un riquadro dei dettagli e un riquadro aggiuntivo facoltativo. che gestisce i calcoli dello spazio sullo schermo. Quando sono disponibili dimensioni dello schermo sufficienti, il riquadro dei dettagli viene visualizzato accanto al riquadro dell'elenco. Sugli schermi di piccole dimensioni, l'impalcatura passa automaticamente alla visualizzazione a schermo intero dell'elenco o del riquadro dei dettagli.

Un riquadro dei dettagli visualizzato accanto alla pagina dell'elenco.
Figura 1. Quando le dimensioni dello schermo sono sufficienti, il riquadro dei dettagli viene visualizzato 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 è stato selezionato un elemento) occupa l'intero spazio.

Dichiara le dipendenze

ListDetailPaneScaffold fa parte della libreria di layout adattivi di Material 3.

L'app deve includere dipendenze per tre librerie Material 3 correlate:

  • Adattivo: componenti di base di basso livello come HingeInfo e Posture
  • Layout adattivo: layout adattivi come ListDetailPaneScaffold e SupportingPaneScaffold
    • Adaptive-navigation: elementi componibili per navigare all'interno e tra i riquadri

Aggiungi le dipendenze al file build.gradle dell'app o del 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")

trendy


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 come segue:

  1. Utilizza una classe che rappresenti i contenuti da selezionare. Questa classe deve essere Parcelable per supportare il salvataggio e il ripristino dell'elemento dell'elenco selezionato. Utilizza il plug-in kotlin-parcelize per generare il codice.

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

  2. Crea un ThreePaneScaffoldNavigator con rememberListDetailPaneScaffoldNavigator e aggiungi un BackHandler. Questo riquadro di navigazione viene utilizzato per spostarti tra l'elenco, i dettagli e i riquadri aggiuntivi. Se dichiari un tipo generico, il navigatore tiene traccia anche dello stato dell'impalcatura (ovvero, MyItem viene visualizzato). Poiché questo tipo è parcellabile, lo stato può essere salvato e ripristinato dal navigatore per gestire automaticamente le modifiche alla configurazione. BackHandler supporta la navigazione indietro utilizzando il pulsante o il gesto Indietro del sistema. Il comportamento previsto del pulsante Indietro per un elemento ListDetailPaneScaffold dipende dalle dimensioni della finestra e dal valore di scaffold corrente. Se ListDetailPaneScaffold può supportare il ripristino dello stato corrente, canNavigateBack() è true e viene abilitato BackHandler.

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

  3. Supera il scaffoldState dal componibile navigator al componibile ListDetailPaneScaffold.

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

  4. Fornisci l'implementazione del riquadro dell'elenco in ListDetailPaneScaffold. Utilizza AnimatedPane per applicare le animazioni predefinite dei riquadri durante la navigazione. Usa quindi ThreePaneScaffoldNavigator per accedere al riquadro dei dettagli ListDetailPaneScaffoldRole.Detail e visualizzare l'elemento superato.

    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 al suo interno. La proprietà content è dello stesso tipo specificato nella chiamata Promemoria originale (MyItem in questo esempio), quindi puoi accedere alla proprietà anche per tutti i dati 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 avere un aspetto simile a questo:

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