Elenco-dettagli è un pattern dell'interfaccia utente costituito da un layout a due riquadri 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 dettagliate sugli elementi di grandi raccolte, ad esempio un client email che ha un elenco di email e il contenuto dettagliato di ogni messaggio email. L'elenco dettagliato 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.


Implementare il pattern elenco-dettaglio con NavigableListDetailPaneScaffold
NavigableListDetailPaneScaffold
è un composable che semplifica l'implementazione di un layout elenco-dettagli in Jetpack Compose. Esegue il wrapping di ListDetailPaneScaffold
e
aggiunge animazioni di navigazione e Indietro predittivo integrate.
Uno scaffold elenco-dettagli supporta fino a tre riquadri:
- Riquadro Elenco: mostra una raccolta di elementi.
- Riquadro dei dettagli: mostra i dettagli di un elemento selezionato.
- Riquadro aggiuntivo (facoltativo): fornisce ulteriore contesto quando necessario.
La struttura si adatta in base alle dimensioni della finestra:
- Nelle finestre grandi, 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'
- adattivi: componenti di base di basso livello come
HingeInfo
ePosture
- adaptive-layout: layout adattivi come
ListDetailPaneScaffold
eSupportingPaneScaffold
- adaptive-navigation: componenti componibili per la navigazione all'interno e tra i riquadri,
nonché layout adattivi che supportano la navigazione per impostazione predefinita, come
NavigableListDetailPaneScaffold
eNavigableSupportingPaneScaffold
Assicurati che il progetto includa compose-material3-adaptive versione 1.1.0-beta1 o successive.
Attivare il gesto Indietro predittivo
Per attivare le animazioni del gesto Indietro predittivo in Android 15 o versioni precedenti, devi attivare
il supporto del gesto Indietro predittivo. Per attivare la funzionalità, aggiungi
android:enableOnBackInvokedCallback="true"
al tag <application>
o
ai singoli tag <activity>
all'interno del file AndroidManifest.xml
. Per ulteriori informazioni, consulta la sezione Attivare la navigazione predittiva.
Una volta che la tua app ha come target Android 16 (livello API 36) o versioni successive, la navigazione predittiva è attivata per impostazione predefinita.
Utilizzo di base
Implementa NavigableListDetailPaneScaffold
nel seguente modo:
- Utilizza una classe che rappresenti i contenuti selezionati. Utilizza una classe
Parcelable
per supportare il salvataggio e il ripristino dell'elemento di elenco selezionato. Utilizza il plug-in kotlin-parcelize per generare il codice. - Crea un
ThreePaneScaffoldNavigator
conrememberListDetailPaneScaffoldNavigator
.
Questo navigatore viene utilizzato per spostarsi tra i riquadri elenco, dettagli e aggiuntivi. Dichiarando un tipo generico, il navigatore tiene traccia anche dello stato dello scaffold
(ovvero quale MyItem
viene visualizzato). Poiché questo tipo è pacchettizzabile, lo stato può essere salvato e ripristinato dal navigatore per gestire automaticamente le modifiche alla configurazione.
Passa il navigatore al composable
NavigableListDetailPaneScaffold
.Fornisci l'implementazione del riquadro dell'elenco al
NavigableListDetailPaneScaffold
. UtilizzaAnimatedPane
per applicare le animazioni predefinite del riquadro durante la navigazione. Poi utilizzaThreePaneScaffoldNavigator
per andare al riquadro dei dettagli,ListDetailPaneScaffoldRole.Detail
, e visualizzare l'elemento passato.Includi l'implementazione del riquadro dei dettagli in
NavigableListDetailPaneScaffold
.
Al termine della navigazione, currentDestination
contiene il riquadro a cui è stata indirizzata la tua app, 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.
- (Facoltativo) Modifica
defaultBackBehavior
inNavigableListDetailPaneScaffold
. Per impostazione predefinita,NavigableListDetailPaneScaffold
utilizzaPopUntilScaffoldValueChange
perdefaultBackBehavior
.
Se la tua app richiede un pattern di navigazione indietro diverso, puoi ignorare questo
comportamento specificando un'altra opzione BackNavigationBehavior
.
BackNavigationBehavior
opzioni
La sezione seguente utilizza l'esempio di un'app di posta elettronica con un elenco di email in un riquadro e una visualizzazione dettagliata nell'altro.
PopUntilScaffoldValueChange
(opzione predefinita e consigliata nella maggior parte dei casi)
Questo comportamento si concentra sulle modifiche alla struttura generale del layout. In una configurazione a più riquadri, la modifica dei contenuti dell'email nel riquadro dei dettagli non altera la struttura del layout sottostante. Pertanto, il pulsante Indietro potrebbe chiudere l'app o il grafico di navigazione corrente perché non è possibile ripristinare alcuna modifica del layout nel contesto attuale. In un layout a un solo riquadro, premendo Indietro si scorreranno le modifiche ai contenuti all'interno della visualizzazione dettagli e si tornerà alla visualizzazione elenco, in quanto ciò rappresenta una chiara modifica del layout.
Considera i seguenti esempi:
- Multipanel: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. Se premi Indietro, potresti uscire dall'app o dal flusso di navigazione corrente.
- Singola finestra:visualizzi l'elemento 1, poi l'elemento 2. Se premi Indietro, tornerai direttamente al riquadro dell'elenco delle email.
Utilizza questa opzione quando vuoi che gli utenti percepiscano transizioni di layout distinte a ogni azione Indietro.

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:
- Multivetrina:visualizzi l'elemento 1 nel riquadro dei dettagli, poi fai clic sull'elemento 2 nell'elenco. Il riquadro dei dettagli viene aggiornato. Se premi Indietro, il riquadro dei dettagli tornerà all'elemento 1.
- Singolo riquadro:si verifica lo stesso ripristino dei contenuti.
Utilizza questo valore quando l'utente si aspetta di tornare ai contenuti visualizzati in precedenza con l'azione Indietro.

PopUntilCurrentDestinationChange
Questo comportamento fa uscire dallo stack precedente fino a quando non cambia la destinazione di navigazione corrente. Questo vale sia per i layout a un solo riquadro sia per quelli a più riquadri.
Considera i seguenti esempi:
Indipendentemente dal layout a un solo riquadro o a più riquadri, se premi Indietro lo stato attivo si sposta sempre dall'elemento di navigazione evidenziato alla destinazione precedente. Nella nostra app di posta, ciò significa che l'indicazione visiva del riquadro selezionato cambierà.
Utilizza questa opzione quando mantenere un'indicazione visiva chiara della navigazione corrente è fondamentale per l'esperienza utente.

PopLatest
Questa opzione rimuove solo la destinazione più recente dallo stack precedente. Utilizza questa opzione per la navigazione indietro senza saltare gli stati intermedi.
Dopo aver implementato questi passaggi, il codice dovrebbe essere simile al seguente:
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) } } }, )