Elenco-dettagli è 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. Il layout elenco-dettagli può essere utilizzato anche per percorsi meno critici, ad esempio per suddividere le preferenze dell'app in un elenco di categorie con le preferenze per ogni categoria nel riquadro dei dettagli.
Implementa il pattern list-detail con NavigableListDetailPaneScaffold
NavigableListDetailPaneScaffold è un composable che semplifica l'implementazione di un layout elenco-dettagli in Jetpack Compose. Esegue il wrapping di ListDetailPaneScaffold e aggiunge la navigazione integrata e le animazioni Indietro predittivo.
Un'impalcatura list-detail 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 un contesto aggiuntivo quando necessario.
Lo scaffold 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.
Dichiarazione di dipendenze
NavigableListDetailPaneScaffold fa parte della libreria di navigazione adattiva di 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")
Alla moda
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
HingeInfoePosture - adaptive-layout: layout adattivi come
ListDetailPaneScaffoldeSupportingPaneScaffold - adaptive-navigation: composabili per la navigazione all'interno e tra i riquadri, nonché layout adattivi che supportano la navigazione per impostazione predefinita, come
NavigableListDetailPaneScaffoldeNavigableSupportingPaneScaffold
Assicurati che il progetto includa compose-material3-adaptive versione 1.1.0-beta1 o successive.
Attiva il gesto Indietro predittivo
Per attivare le animazioni di Indietro predittivo in Android 15 o versioni precedenti, devi attivare il supporto del 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 saperne di più, consulta Attiva il gesto Indietro predittivo.
Se 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:
- Utilizza una classe che rappresenti i contenuti selezionati. Utilizza una classe
Parcelableper supportare il salvataggio e il ripristino dell'elemento dell'elenco selezionato. Utilizza il plug-in kotlin-parcelize per generare il codice. - Crea un
ThreePaneScaffoldNavigatorconrememberListDetailPaneScaffoldNavigator.
Questo strumento di navigazione viene utilizzato per spostarsi tra i riquadri dell'elenco, dei dettagli e aggiuntivi. Dichiarando un tipo generico, il navigatore monitora anche lo stato dello scaffold (ovvero quale MyItem viene visualizzato). Poiché questo tipo è parcelable, lo stato può essere salvato e ripristinato dal navigatore per gestire automaticamente le modifiche alla configurazione.
Passa il navigatore al componibile
NavigableListDetailPaneScaffold.Fornisci l'implementazione del riquadro dell'elenco a
NavigableListDetailPaneScaffold. UtilizzaAnimatedPaneper applicare le animazioni predefinite del riquadro durante la navigazione. Poi utilizzaThreePaneScaffoldNavigatorper passare 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 l'app ha eseguito la navigazione, 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.
- Se vuoi, modifica il
defaultBackBehaviorinNavigableListDetailPaneScaffold. Per impostazione predefinita,NavigableListDetailPaneScaffoldutilizzaPopUntilScaffoldValueChangeperdefaultBackBehavior.
Se la tua app richiede un pattern di navigazione a ritroso diverso, puoi eseguire l'override di questo comportamento specificando un'altra opzione BackNavigationBehavior.
BackNavigationBehavior opzioni
La sezione seguente utilizza l'esempio di un'app email con un elenco di email in un riquadro e una visualizzazione dettagliata nell'altro.
PopUntilScaffoldValueChange (impostazione predefinita e consigliata nella maggior parte dei casi)
Questo comportamento si concentra sulle modifiche alla struttura complessiva del layout. In una configurazione con più riquadri, la modifica dei contenuti dell'email nel riquadro dei dettagli non altera la struttura del layout sottostante. Pertanto, il pulsante Indietro potrebbe uscire dall'app o dal grafico di navigazione corrente perché non è presente alcuna modifica del layout a cui tornare nel contesto corrente. In un layout a riquadro singolo, premendo Indietro si saltano le modifiche ai contenuti all'interno della visualizzazione dettagliata e si torna alla visualizzazione elenco, poiché ciò rappresenta una chiara modifica del layout.
Considera i seguenti esempi:
- Multi-riquadro: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.
- Riquadro singolo:visualizzi l'elemento 1, poi l'elemento 2. Se premi Indietro, torni direttamente al riquadro dell'elenco delle email.
Utilizza questa opzione se vuoi che gli utenti percepiscano transizioni di layout distinte con 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:
- Più riquadri: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 torna all'elemento 1.
- Schermo 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.
PopUntilCurrentDestinationChange
Questo comportamento rimuove il back stack fino a quando la destinazione di navigazione corrente non cambia. Questo vale sia per i layout a riquadro singolo che per quelli a più riquadri.
Considera i seguenti esempi:
Indipendentemente dal fatto che tu stia utilizzando un layout a uno o più riquadri, premendo il tasto Indietro lo stato attivo 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 per l'esperienza utente mantenere un'indicazione visiva chiara della navigazione corrente.
PopLatest
Questa opzione rimuove solo la destinazione più recente dal backstack. Utilizza questa opzione per la navigazione a ritroso senza saltare gli stati intermedi.
Dopo aver implementato questi passaggi, il codice dovrebbe essere 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 ) } } ) } }