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.
Implementare il pattern elenco dettagliato con NavigableListDetailPaneScaffold
NavigableListDetailPaneScaffold è un componibile 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 list-detail supporta fino a tre riquadri:
- Riquadro dell'elenco: mostra una raccolta di elementi.
- Riquadro dei dettagli: mostra i dettagli di un elemento selezionato.
- 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.
Dichiarazione di 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")
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: componibili per la navigazione all'interno e tra i riquadri, nonché layout adattivi che supportano la navigazione per impostazione predefinita, come
NavigableListDetailPaneScaffoldeNavigableSupportingPaneScaffold
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, 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, Indietro predittivo è attivato per impostazione predefinita.
Utilizzo di base
Implementa NavigableListDetailPaneScaffold come segue:
- Utilizza una classe che rappresenta i contenuti selezionati. Utilizza una
Parcelableclasse per 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 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 è 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 in cui è stata spostata l'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
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.
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.
PopUntilScaffoldValueChange (impostazione 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 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 è presente alcuna modifica del layout a cui tornare nel contesto corrente. In un layout a un solo riquadro, premendo Indietro si salteranno le modifiche ai contenuti all'interno della 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.
- Un solo riquadro: 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.
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.
- Un solo riquadro: 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 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 fatto che tu stia utilizzando un layout a un solo riquadro o a più riquadri, premendo Indietro il focus si sposterà sempre dall'elemento di navigazione evidenziato alla destinazione precedente. Nella nostra app email, ciò significa che l'indicazione visiva del riquadro selezionato cambierà.
Utilizza questa opzione quando il mantenimento di un'indicazione visiva chiara della navigazione corrente è fondamentale per l'esperienza utente.
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 ) } } ) } }