Układ panelu pomocniczego pozwala użytkownikowi skupić się na głównej zawartości aplikacji, a jednocześnie wyświetlać istotne informacje pomocnicze. Na przykład w głównym panelu mogą być wyświetlane szczegóły filmu, a w panelu pomocniczym – podobne filmy, filmy tego samego reżysera lub filmy z tymi samymi aktorami.
Więcej informacji znajdziesz w wytycznych dotyczących panelu pomocniczego Material 3.
Implementowanie panelu pomocniczego z użyciem szkieletu
NavigableSupportingPaneScaffold
to komponent, który upraszcza implementację układu panelu pomocniczego w Jetpack Compose. Zawiera SupportingPaneScaffold
oraz wbudowaną nawigację i predykcyjne obsługiwanie gestu wstecz.
Struktura panelu pomocniczego może zawierać maksymalnie 3 panele:
- Główny panel: wyświetla główną zawartość.
- Panel pomocniczy: zawiera dodatkowy kontekst lub narzędzia związane z panelem głównym.
- Dodatkowy panel (opcjonalny): używany w razie potrzeby do wyświetlania dodatkowych treści.
Szkielet dostosowuje się do rozmiaru okna:
- W przypadku dużych okien panele główny i pomocniczy wyświetlają się obok siebie.
W małych oknach widoczny jest tylko jeden panel naraz, który zmienia się w miarę poruszania się użytkowników.
Rysunek 1. Układ panelu pomocniczego.
Dodawanie zależności
NavigableSupportingPaneScaffold
jest częścią biblioteki układów adaptacyjnych Material 3.
Dodaj do pliku build.gradle
aplikacji lub modułu te 3 zależności:
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'
adaptacyjne: elementy składowe niskiego poziomu, takie jak
HingeInfo
iPosture
;adaptive-layout: układy adaptacyjne, np.
ListDetailPaneScaffold
iSupportingPaneScaffold
adaptive-navigation: komponenty kompozycyjne do nawigacji w panelach i między nimi, a także układy adaptacyjne, które domyślnie obsługują nawigację, np.
NavigableListDetailPaneScaffold
iNavigableSupportingPaneScaffold
.
Upewnij się, że projekt zawiera bibliotekę compose-material3-adaptive w wersji 1.1.0-beta1 lub nowszej.
Włączanie gestu przewidywanego przejścia wstecz
Aby włączyć animacje przewidywanego przejścia wstecz w Androidzie 15 lub starszym, musisz wyrazić zgodę na obsługę gestu przewidywanego przejścia wstecz. Aby wyrazić zgodę, dodaj
android:enableOnBackInvokedCallback="true"
do tagu <application>
lub do poszczególnych tagów <activity>
w pliku AndroidManifest.xml
.
Gdy aplikacja jest kierowana na Androida 16 (API na poziomie 36) lub nowszego, funkcja przewidywanego powrotu jest domyślnie włączona.
Tworzenie nawigatora
W małych oknach wyświetlany jest tylko jeden panel naraz, więc do przełączania się między panelami używaj ThreePaneScaffoldNavigator
. Utwórz instancję nawigatora za pomocą funkcji rememberSupportingPaneScaffoldNavigator
.
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope()
Przekaż nawigator do elementu Scaffold
Szkielet wymaga ThreePaneScaffoldNavigator
, czyli interfejsu reprezentującego stan szkieletu, ThreePaneScaffoldValue
i PaneScaffoldDirective
.
NavigableSupportingPaneScaffold( navigator = scaffoldNavigator, mainPane = { /*...*/ }, supportingPane = { /*...*/ }, )
Główny i pomocniczy panel to komponenty zawierające Twoje treści. Użyj
AnimatedPane
, aby podczas nawigacji zastosować domyślne animacje panelu. Użyj wartości struktury, aby sprawdzić, czy panel pomocniczy jest ukryty. Jeśli tak, wyświetl przycisk, który wywołuje funkcję navigateTo(SupportingPaneScaffoldRole.Supporting)
, aby wyświetlić panel pomocniczy.
Oto pełna implementacja szkieletu:
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") } } )
Wyodrębnianie funkcji kompozycyjnych z panelu
Wyodrębnij poszczególne panele SupportingPaneScaffold
do osobnych komponentów kompozycyjnych, aby można było ich używać ponownie i testować. Aby uzyskać dostęp do AnimatedPane
, użyj ThreePaneScaffoldScope
, jeśli chcesz używać domyślnych animacji:
@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") } }
Wyodrębnienie paneli do funkcji kompozycyjnych upraszcza korzystanie z elementu
SupportingPaneScaffold
(porównaj to z pełną implementacją
elementu Scaffold w poprzedniej sekcji):
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() }, )
Jeśli chcesz mieć większą kontrolę nad konkretnymi aspektami szkieletu, użyj SupportingPaneScaffold
zamiast NavigableSupportingPaneScaffold
. Ta funkcja akceptuje oddzielnie wartości PaneScaffoldDirective
i ThreePaneScaffoldValue
lub ThreePaneScaffoldState
. Ta elastyczność pozwala wdrożyć niestandardową logikę odstępów między panelami i określić, ile paneli ma być wyświetlanych jednocześnie. Możesz też włączyć obsługę przewidywanego powrotu, dodając
ThreePaneScaffoldPredictiveBackHandler
.
Dodaj ThreePaneScaffoldPredictiveBackHandler
Dołącz moduł obsługi przewidywanego przejścia wstecz, który przyjmuje instancję nawigatora szkieletowego i określa backBehavior
. Określa, jak miejsca docelowe są usuwane ze stosu wstecznego podczas nawigacji wstecznej. Następnie przesuń scaffoldDirective
i scaffoldState
do SupportingPaneScaffold
. Użyj przeciążenia, które akceptuje
ThreePaneScaffoldState
, przekazując scaffoldNavigator.scaffoldState
.
Określ główne i pomocnicze panele w SupportingPaneScaffold
. Użyj
AnimatedPane
w przypadku domyślnych animacji paneli.
Po wykonaniu tych czynności kod powinien wyglądać podobnie do tego:
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() }, )