Crea un layout elenco-dettagli

L'elenco dettagliato è 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 raccolte di grandi dimensioni, ad esempio un client di posta che ha un elenco di email e il contenuto dettagliato di ogni messaggio email. Il list-detail può essere utilizzato anche per percorsi meno critici, ad esempio per dividere le preferenze dell'app in un elenco di categorie con le preferenze per ogni categoria nel riquadro dei dettagli.

Un riquadro dei dettagli visualizzato accanto alla pagina dell'elenco.
Figura 1. Quando è disponibile spazio sufficiente sullo schermo, il riquadro dei dettagli viene visualizzato accanto al riquadro dell'elenco.
Una volta selezionato un elemento, il riquadro dei dettagli occupa l'intera schermata.
Figura 2. Quando le dimensioni dello schermo sono limitate, il riquadro dei dettagli (poiché è stato selezionato un elemento) occupa tutto lo spazio.

Implementare il pattern elenco dettagliato con NavigableListDetailPaneScaffold

NavigableListDetailPaneScaffold è un elemento componibile che semplifica l'implementazione di un layout elenco-dettagliato in Jetpack Compose. Esegue il wrapping di ListDetailPaneScaffold e aggiunge animazioni di navigazione e Indietro predittivo integrate.

Uno scaffold list-detail supporta fino a tre riquadri:

  1. Riquadro dell'elenco: mostra una raccolta di elementi.
  2. Riquadro dei dettagli: mostra i dettagli di un elemento selezionato.
  3. Riquadro extra (facoltativo): fornisce un contesto aggiuntivo quando necessario.

Lo scaffold si adatta in base alle dimensioni della finestra:

  • Nelle finestre di grandi dimensioni, i riquadri dell'elenco e dei dettagli vengono visualizzati uno accanto all'altro.
  • Nelle finestre piccole, è visibile un solo riquadro alla volta, che cambia man mano che gli utenti navigano.

Dichiarare le dipendenze

NavigableListDetailPaneScaffold fa parte della libreria di navigazione adattiva Material 3 .

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

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: componenti di base di basso livello come HingeInfo e Posture
  • adaptive-layout: layout adattivi come ListDetailPaneScaffold e SupportingPaneScaffold
  • adaptive-navigation: elementi componibili per la navigazione all'interno e tra i riquadri, nonché layout adattivi che supportano la navigazione per impostazione predefinita, come NavigableListDetailPaneScaffold e NavigableSupportingPaneScaffold

Assicurati che il tuo progetto includa compose-material3-adaptive versione 1.1.0-beta1 o successive.

Attivare il gesto Indietro predittivo

Per attivare le animazioni Indietro predittivo in Android 15 o versioni precedenti, devi attivare il supporto per il gesto Indietro predittivo. Per attivare questa funzionalità, aggiungi android:enableOnBackInvokedCallback="true" al tag <application> o ai singoli tag <activity> all'interno del file AndroidManifest.xml. Per ulteriori informazioni, consulta Attivare il gesto Indietro predittivo.

Una volta che la tua app ha come target Android 16 (livello API 36) o versioni successive, la funzionalità Indietro predittivo è attivata per impostazione predefinita.

Utilizzo di base

Implementa NavigableListDetailPaneScaffold come segue:

  1. Utilizza una classe che rappresenta i contenuti selezionati. Utilizza una Parcelable classe per supportare il salvataggio e il ripristino dell'elemento dell'elenco selezionato. Utilizza il plug-in kotlin-parcelize per generare il codice.
  2. Crea un ThreePaneScaffoldNavigator con rememberListDetailPaneScaffoldNavigator.

Questo navigatore viene utilizzato per spostarsi tra i riquadri dell'elenco, dei dettagli e extra. Dichiarando un tipo generico, il navigatore tiene traccia anche dello stato dello scaffold (ovvero quale MyItem viene visualizzato). Poiché questo tipo è serializzabile, lo stato può essere salvato e ripristinato dal navigatore per gestire automaticamente le modifiche alla configurazione.

  1. Passa il navigatore all'elemento componibile NavigableListDetailPaneScaffold.

  2. Fornisci l'implementazione del riquadro dell'elenco a NavigableListDetailPaneScaffold. Utilizza AnimatedPane per applicare le animazioni predefinite del riquadro durante la navigazione. Poi utilizza ThreePaneScaffoldNavigator per passare al riquadro dei dettagli, ListDetailPaneScaffoldRole.Detail, e visualizzare l'elemento passato.

  3. Includi l'implementazione del riquadro dei dettagli in NavigableListDetailPaneScaffold.

Al termine della navigazione, currentDestination contiene il riquadro in cui l'app ha navigato, inclusi i contenuti visualizzati nel riquadro. La proprietà contentKey è dello stesso tipo specificato nella chiamata originale, quindi puoi accedere a tutti i dati che devi visualizzare.

  1. (Facoltativo) Modifica defaultBackBehavior in NavigableListDetailPaneScaffold. Per impostazione predefinita, NavigableListDetailPaneScaffold utilizza PopUntilScaffoldValueChange per defaultBackBehavior.

Se la tua app richiede un pattern di navigazione a ritroso diverso, puoi eseguire l'override di questo comportamento specificando un'altra opzione BackNavigationBehavior.

Opzioni BackNavigationBehavior

La sezione seguente utilizza l'esempio di un'app email con un elenco di email in un riquadro e una visualizzazione dettagliata nell'altro.

Questo comportamento si concentra sulle modifiche alla struttura generale del layout. In una configurazione a più riquadri, la modifica dei contenuti email nel riquadro dei dettagli non altera la struttura del layout sottostante. Di conseguenza, il pulsante Indietro potrebbe uscire dall'app o dal grafico di navigazione corrente perché non è possibile ripristinare alcuna modifica del layout nel contesto corrente. In un layout a riquadro singolo, premendo Indietro si salteranno le modifiche dei contenuti nella visualizzazione dei dettagli e si tornerà alla visualizzazione dell'elenco, poiché ciò rappresenta una chiara modifica del layout.

Considera i seguenti esempi:

  • Più riquadri: stai visualizzando un'email (elemento 1) nel riquadro dei dettagli. Se fai clic su un'altra email (elemento 2), il riquadro dei dettagli viene aggiornato, ma i riquadri dell'elenco e dei dettagli rimangono visibili. Premendo Indietro potresti uscire dall'app o dal flusso di navigazione corrente.
  • Riquadro singolo: se visualizzi l'elemento 1 e poi l'elemento 2, premendo Indietro tornerai direttamente al riquadro dell'elenco delle email.

Utilizza questa opzione quando vuoi che gli utenti percepiscano transizioni di layout distinte con ogni azione Indietro.

Modifica del valore di navigazione.
PopUntilContentChange

Questo comportamento dà la priorità ai contenuti visualizzati. Se visualizzi l'elemento 1 e poi l'elemento 2, premendo Indietro tornerai all'elemento 1, indipendentemente dal layout.

Considera i seguenti esempi:

  • Più riquadri: visualizzi l'elemento 1 nel riquadro dei dettagli, poi fai clic sull'elemento 2 nell'elenco. Il riquadro dei dettagli viene aggiornato. Premendo Indietro, il riquadro dei dettagli verrà ripristinato all'elemento 1.
  • Riquadro singolo: si verifica la stessa inversione dei contenuti.

Utilizza questa opzione quando l'utente si aspetta di tornare ai contenuti visualizzati in precedenza con l'azione Indietro.

la transizione tra due riquadri dei dettagli
PopUntilCurrentDestinationChange

Questo comportamento rimuove gli elementi dallo stack Indietro fino a quando non cambia la destinazione di navigazione corrente. Questo vale sia per i layout a riquadro singolo sia per quelli a più riquadri.

Considera i seguenti esempi:

Indipendentemente dal fatto che tu stia utilizzando un layout a riquadro singolo o a più riquadri, premendo Indietro il focus si sposterà sempre dall'elemento di navigazione evidenziato alla destinazione precedente. Nella nostra app email, questo significa che l'indicazione visiva del riquadro selezionato cambierà.

Utilizza questa opzione quando è fondamentale mantenere un'indicazione visiva chiara della navigazione corrente per l'esperienza utente.

navigazione tra i riquadri dei dettagli e dell&#39;elenco
PopLatest

Questa opzione rimuove solo la destinazione più recente dallo stack Indietro. Utilizza questa opzione per la navigazione a ritroso senza saltare gli stati intermedi.

Dopo aver implementato questi passaggi, il codice dovrebbe avere un aspetto simile al seguente:

NavigableListDetailPaneScaffold(
    navigator = navigator,
    listPane = {
        AnimatedPane {
            ListContent(
                words = sampleWords,
                selectionState = navigator.currentDestination?.contentKey?.let {
                    SelectionVisibilityState.ShowSelection(it)
                } ?: SelectionVisibilityState.NoSelection,
                onWordClick = { word ->
                    scope.launch {
                        navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, word)
                    }
                },
                animatedVisibilityScope = this@AnimatedPane,
                sharedTransitionScope = this@SharedTransitionLayout
            )
        }
    },
    detailPane = {
        AnimatedPane {
            DetailContent(
                definedWord = navigator.currentDestination?.contentKey,
                animatedVisibilityScope = this@AnimatedPane,
                sharedTransitionScope = this@SharedTransitionLayout,
                onClosePane = {
                    scope.launch {
                        navigator.navigateBack(
                            backNavigationBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange
                        )

                    }
                }
            )
        }
    }