Das Layout mit unterstützendem Bereich sorgt dafür, dass der Fokus des Nutzers auf dem Hauptinhalt der App bleibt, während relevante unterstützende Informationen angezeigt werden. Im Hauptbereich können beispielsweise Details zu einem Film angezeigt werden, während im unterstützenden Bereich ähnliche Filme, Filme desselben Regisseurs oder Werke mit denselben Schauspielern aufgeführt werden.
Weitere Informationen findest du in den Richtlinien für den unterstützenden Bereich von Material 3.
Unterstützenden Bereich mit einem Scaffold implementieren
NavigableSupportingPaneScaffold ist eine zusammensetzbare Funktion, die die Implementierung eines Layouts mit unterstützendem Bereich in Jetpack Compose vereinfacht. Es umschließt SupportingPaneScaffold und fügt integrierte Navigation und die Verarbeitung von intelligenten „Zurück“-Gesten hinzu.
Ein Scaffold für einen unterstützenden Bereich unterstützt bis zu drei Bereiche:
- Hauptbereich: Hier werden die primären Inhalte angezeigt.
- Unterstützender Bereich: Bietet zusätzlichen Kontext oder Tools, die sich auf den Hauptbereich beziehen.
- Zusätzlicher Bereich (optional): Wird bei Bedarf für ergänzende Inhalte verwendet.
Das Scaffold wird an die Fenstergröße angepasst:
- In großen Fenstern werden der Haupt- und der Nebenbereich nebeneinander angezeigt.
In kleinen Fenstern ist jeweils nur ein Bereich sichtbar. Der Bereich wechselt, wenn Nutzer navigieren.
Abbildung 1. Layout des unterstützenden Bereichs.
Abhängigkeiten hinzufügen
NavigableSupportingPaneScaffold ist Teil der Material 3-Bibliothek für adaptive Layouts.
Fügen Sie der Datei build.gradle Ihrer App oder Ihres Moduls die folgenden drei zugehörigen Abhängigkeiten hinzu:
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: Bausteine auf niedriger Ebene wie
HingeInfoundPostureadaptive-layout: Adaptive Layouts wie
ListDetailPaneScaffoldundSupportingPaneScaffoldadaptive-navigation: Composables für die Navigation innerhalb von und zwischen Bereichen sowie adaptive Layouts, die die Navigation standardmäßig unterstützen, z. B.
NavigableListDetailPaneScaffoldundNavigableSupportingPaneScaffold
Prüfen Sie, ob Ihr Projekt compose-material3-adaptive Version 1.1.0-beta1 oder höher enthält.
Intelligente „Zurück“-Touchgeste aktivieren
Wenn Sie die intelligente „Zurück“-Touchgeste in Android 15 oder niedriger aktivieren möchten, müssen Sie die Unterstützung für die intelligente „Zurück“-Touchgeste aktivieren. Wenn du die Funktion aktivieren möchtest, füge android:enableOnBackInvokedCallback="true" zum Tag <application> oder zu einzelnen <activity>-Tags in deiner AndroidManifest.xml-Datei hinzu.
Wenn Ihre App auf Android 16 (API-Level 36) oder höher ausgerichtet ist, ist die intelligente „Zurück“-Geste standardmäßig aktiviert.
Navigator erstellen
In kleinen Fenstern wird jeweils nur ein Bereich angezeigt. Verwenden Sie daher ein ThreePaneScaffoldNavigator, um zwischen den Bereichen zu wechseln. Erstellen Sie mit rememberSupportingPaneScaffoldNavigator eine Instanz des Navigators.
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope()
Navigator an das Scaffold übergeben
Das Scaffold erfordert einen ThreePaneScaffoldNavigator, eine Schnittstelle, die den Status des Scaffolds darstellt, den ThreePaneScaffoldValue und einen PaneScaffoldDirective.
NavigableSupportingPaneScaffold( navigator = scaffoldNavigator, mainPane = { /*...*/ }, supportingPane = { /*...*/ }, )
Der Hauptbereich und der unterstützende Bereich sind zusammensetzbare Funktionen, die Ihre Inhalte enthalten. Verwenden Sie AnimatedPane, um die Standardanimationen für Bereiche während der Navigation anzuwenden. Prüfen Sie mit dem Scaffold-Wert, ob der unterstützende Bereich ausgeblendet ist. Wenn ja, zeigen Sie eine Schaltfläche an, die navigateTo(SupportingPaneScaffoldRole.Supporting) aufruft, um den unterstützenden Bereich einzublenden.
Verwenden Sie für große Bildschirme die Methode ThreePaneScaffoldNavigator.navigateBack(), um den unterstützenden Bereich zu schließen, und übergeben Sie die Konstante BackNavigationBehavior.PopUntilScaffoldValueChange. Durch den Aufruf dieser Methode wird eine Neuzusammensetzung des NavigableSupportingPaneScaffold erzwungen.
Prüfen Sie während der Neuzusammensetzung das Attribut ThreePaneScaffoldNavigator.currentDestination, um festzustellen, ob der unterstützende Bereich angezeigt werden soll.
Hier ist eine vollständige Implementierung des Scaffolds:
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope() val backNavigationBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange 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()) { Column { // Allow users to dismiss the supporting pane. Use back navigation to // hide an expanded supporting pane. if (scaffoldNavigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Expanded) { // Material design principles promote the usage of a right-aligned // close (X) button. IconButton( modifier = Modifier.align(Alignment.End).padding(16.dp), onClick = { scope.launch { scaffoldNavigator.navigateBack(backNavigationBehavior) } } ) { Icon(Icons.Default.Close, contentDescription = "Close") } } Text("Supporting pane") } } } )
Bereichs-Composables extrahieren
Extrahieren Sie die einzelnen Bereiche eines SupportingPaneScaffold in eigene Composables, um sie wiederverwendbar und testbar zu machen. Verwenden Sie ThreePaneScaffoldScope, um auf AnimatedPane zuzugreifen, wenn Sie die Standardanimationen verwenden möchten:
@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( scaffoldNavigator: ThreePaneScaffoldNavigator<Any>, modifier: Modifier = Modifier, backNavigationBehavior: BackNavigationBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange, ) { val scope = rememberCoroutineScope() AnimatedPane(modifier = Modifier.safeContentPadding()) { Column { // Allow users to dismiss the supporting pane. Use back navigation to // hide an expanded supporting pane. if (scaffoldNavigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Expanded) { // Material design principles promote the usage of a right-aligned // close (X) button. IconButton( modifier = modifier.align(Alignment.End).padding(16.dp), onClick = { scope.launch { scaffoldNavigator.navigateBack(backNavigationBehavior) } } ) { Icon(Icons.Default.Close, contentDescription = "Close") } } Text("Supporting pane") } } }
Wenn Sie die Bereiche in Composables extrahieren, wird die Verwendung des SupportingPaneScaffold vereinfacht. Vergleichen Sie dazu die folgende Implementierung mit der vollständigen Implementierung des Scaffolds im vorherigen Abschnitt:
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(scaffoldNavigator = scaffoldNavigator) }, )
Wenn Sie bestimmte Aspekte des Scaffolds genauer steuern möchten, sollten Sie SupportingPaneScaffold anstelle von NavigableSupportingPaneScaffold verwenden. Hier werden PaneScaffoldDirective und ThreePaneScaffoldValue oder ThreePaneScaffoldState separat akzeptiert. Dank dieser Flexibilität können Sie eine benutzerdefinierte Logik für den Abstand zwischen den Bereichen implementieren und festlegen, wie viele Bereiche gleichzeitig angezeigt werden sollen. Sie können die Unterstützung für die intelligente „Zurück“-Geste auch aktivieren, indem Sie ThreePaneScaffoldPredictiveBackHandler hinzufügen.
ThreePaneScaffoldPredictiveBackHandler hinzufügen
Hängen Sie den Handler für die intelligente „Zurück“-Geste an, der eine Scaffold-Navigator-Instanz verwendet, und geben Sie die backBehavior an. Damit wird festgelegt, wie Ziele bei der Rückwärtsnavigation aus dem Backstack entfernt werden. Übergeben Sie dann scaffoldDirective und scaffoldState an SupportingPaneScaffold. Verwenden Sie die Überladung, die ein ThreePaneScaffoldState akzeptiert, und übergeben Sie scaffoldNavigator.scaffoldState.
Definiere den Haupt- und den Nebenbereich in SupportingPaneScaffold. Verwenden Sie AnimatedPane für Standardanimationen für Bereiche.
Nachdem Sie diese Schritte ausgeführt haben, sollte Ihr Code in etwa so aussehen:
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(scaffoldNavigator = scaffoldNavigator) }, )