Il layout del riquadro di supporto mantiene l'attenzione dell'utente sui contenuti principali dell'app mentre vengono visualizzate informazioni di supporto pertinenti. Ad esempio, il riquadro principale potrebbe mostrare i dettagli di un film, mentre il riquadro secondario elenca film simili, film dello stesso regista o opere con gli stessi attori.
Per maggiori dettagli, consulta le linee guida per il riquadro di supporto di Material 3.
Implementa un riquadro di supporto con una struttura
NavigableSupportingPaneScaffold
è un composable che semplifica
l'implementazione di un layout del riquadro di supporto in Jetpack Compose. Esegue il wrapping di
SupportingPaneScaffold
e aggiunge la navigazione integrata e la gestione della cronologia predittiva.
Un'impalcatura del riquadro di supporto supporta fino a tre riquadri:
- Riquadro principale: mostra i contenuti principali.
- Riquadro di supporto: fornisce contesto o strumenti aggiuntivi correlati al riquadro principale.
- Riquadro aggiuntivo (facoltativo): utilizzato per i contenuti supplementari, se necessario.
La struttura si adatta in base alle dimensioni della finestra:
- Nelle finestre grandi, i riquadri principale e secondario vengono visualizzati uno accanto all'altro.
Nelle finestre piccole, è visibile un solo riquadro alla volta, che cambia man mano che gli utenti navigano.
Figura 1. Supporto del layout del riquadro.
Aggiungi dipendenze
NavigableSupportingPaneScaffold
fa parte della libreria di layout adattivi 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")
Trendy
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: composable per navigare 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
.
Una volta che la tua app ha come target Android 16 (livello API 36) o versioni successive, la navigazione predittiva è attivata per impostazione predefinita.
Crea un navigatore
Nelle finestre piccole, viene visualizzato un solo riquadro alla volta, quindi utilizza un
ThreePaneScaffoldNavigator
per spostarti tra i riquadri. Crea un'istanza
del navigatore con rememberSupportingPaneScaffoldNavigator
.
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope()
Passa il navigatore allo scaffold
Lo scaffold richiede un ThreePaneScaffoldNavigator
, ovvero un'interfaccia
che rappresenta lo stato dello scaffold, ThreePaneScaffoldValue
e un
PaneScaffoldDirective
.
NavigableSupportingPaneScaffold( navigator = scaffoldNavigator, mainPane = { /*...*/ }, supportingPane = { /*...*/ }, )
Il riquadro principale e quello di supporto sono composable che contengono i tuoi contenuti. Utilizza
AnimatedPane
per applicare le animazioni predefinite del riquadro durante la navigazione. Utilizza
il valore dello scaffold per verificare se il riquadro di supporto è nascosto. In caso affermativo,
visualizza un pulsante che chiama
navigateTo(SupportingPaneScaffoldRole.Supporting)
per visualizzare il
riquadro di supporto.
Ecco un'implementazione completa dello scaffold:
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope() NavigableSupportingPaneScaffold( navigator = scaffoldNavigator, mainPane = { AnimatedPane( modifier = Modifier .safeContentPadding() .background(Color.Red) ) { if (scaffoldNavigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Hidden) { Button( modifier = Modifier .wrapContentSize(), onClick = { scope.launch { scaffoldNavigator.navigateTo(SupportingPaneScaffoldRole.Supporting) } } ) { Text("Show supporting pane") } } else { Text("Supporting pane is shown") } } }, supportingPane = { AnimatedPane(modifier = Modifier.safeContentPadding()) { Text("Supporting pane") } } )
Componenti componibili del riquadro Estrai
Estrai i singoli riquadri di un SupportingPaneScaffold
nei propri
componenti componibili per renderli riutilizzabili e testabili. Utilizza ThreePaneScaffoldScope
per accedere a AnimatedPane
se vuoi le animazioni predefinite:
@OptIn(ExperimentalMaterial3AdaptiveApi::class) @Composable fun ThreePaneScaffoldPaneScope.MainPane( shouldShowSupportingPaneButton: Boolean, onNavigateToSupportingPane: () -> Unit, modifier: Modifier = Modifier, ) { AnimatedPane( modifier = modifier.safeContentPadding() ) { // Main pane content if (shouldShowSupportingPaneButton) { Button(onClick = onNavigateToSupportingPane) { Text("Show supporting pane") } } else { Text("Supporting pane is shown") } } } @OptIn(ExperimentalMaterial3AdaptiveApi::class) @Composable fun ThreePaneScaffoldPaneScope.SupportingPane( modifier: Modifier = Modifier, ) { AnimatedPane(modifier = modifier.safeContentPadding()) { // Supporting pane content Text("This is the supporting pane") } }
L'estrazione dei riquadri in componibili semplifica l'utilizzo di
SupportingPaneScaffold
(confronta quanto segue con l'implementazione completa
dello scaffold nella sezione precedente):
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope() NavigableSupportingPaneScaffold( navigator = scaffoldNavigator, mainPane = { MainPane( shouldShowSupportingPaneButton = scaffoldNavigator.scaffoldValue.secondary == PaneAdaptedValue.Hidden, onNavigateToSupportingPane = { scope.launch { scaffoldNavigator.navigateTo(ThreePaneScaffoldRole.Secondary) } } ) }, supportingPane = { SupportingPane() }, )
Se hai bisogno di un maggiore controllo su aspetti specifici della struttura, valuta l'utilizzo di
SupportingPaneScaffold
anziché di NavigableSupportingPaneScaffold
. Questo
accetta PaneScaffoldDirective
e ThreePaneScaffoldValue
o
ThreePaneScaffoldState
separatamente. Questa flessibilità ti consente di implementare
una logica personalizzata per la spaziatura dei riquadri e determinare quanti riquadri devono essere visualizzati
contemporaneamente. Puoi anche attivare il supporto della navigazione predittiva aggiungendo
ThreePaneScaffoldPredictiveBackHandler
.
Aggiungi ThreePaneScaffoldPredictiveBackHandler
Collega il gestore del gesto Indietro predittivo che accetta un'istanza di Scaffold Navigator e
specifica backBehavior
. Determina come le destinazioni vengono rimosse dallo
stack precedente durante la navigazione indietro. Poi passa scaffoldDirective
e
scaffoldState
a SupportingPaneScaffold
. Utilizza l'overload che accetta un
ThreePaneScaffoldState
, passando scaffoldNavigator.scaffoldState
.
Definisci i riquadri principale e secondario all'interno di SupportingPaneScaffold
. Utilizza
AnimatedPane
per le animazioni predefinite del riquadro.
Dopo aver implementato questi passaggi, il codice dovrebbe essere simile al seguente:
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope() ThreePaneScaffoldPredictiveBackHandler( navigator = scaffoldNavigator, backBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange ) SupportingPaneScaffold( directive = scaffoldNavigator.scaffoldDirective, scaffoldState = scaffoldNavigator.scaffoldState, mainPane = { MainPane( shouldShowSupportingPaneButton = scaffoldNavigator.scaffoldValue.secondary == PaneAdaptedValue.Hidden, onNavigateToSupportingPane = { scope.launch { scaffoldNavigator.navigateTo(ThreePaneScaffoldRole.Secondary) } } ) }, supportingPane = { SupportingPane() }, )