Lista z szczegółami to wzór interfejsu, który składa się z dwóch paneli. Jeden z nich zawiera listę elementów, a drugi – szczegóły elementów wybranych z listy.
Ten wzór jest szczególnie przydatny w przypadku aplikacji, które dostarczają szczegółowych informacji o elementach dużych kolekcji, np. klienta poczty e-mail z listą e-maili i szczegółowymi treściami każdego e-maila. Lista–szczegóły może być też używana na mniej istotnych ścieżkach, np. do podziału preferencji aplikacji na listę kategorii z preferencjami dla każdej kategorii w panelu szczegółów.
Wdrażanie wzorca interfejsu użytkownika za pomocą ListDetailPaneScaffold
ListDetailPaneScaffold
to komponent, który upraszcza implementację w aplikacji wzorca listy i szczegółów. Szkielet listy i szczegółów może składać się z maksymalnie 3 paneli: panelu listy, panelu szczegółów i opcjonalnego dodatkowego panelu. Szkielet obsługuje obliczenia dotyczące miejsca na ekranie. Jeśli rozmiar ekranu jest wystarczający, panel szczegółów jest wyświetlany obok panelu listy. Na małych ekranach automatycznie przełącza się na wyświetlanie listy lub panelu szczegółów na pełnym ekranie.
Deklarowanie zależności
ListDetailPaneScaffold
jest częścią biblioteki Material 3 z dopasowywaniem układu.
Dodaj do pliku build.gradle
aplikacji lub modułu te 3 powiązane 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'
- adaptive – elementy składowe niskiego poziomu, takie jak
HingeInfo
iPosture
. - adaptive-layout – układy adaptacyjne, takie jak
ListDetailPaneScaffold
iSupportingPaneScaffold
- adaptive-navigation – komponenty do nawigacji w obrębie paneli i między nimi
Podstawowe użycie
Zaimplementuj dyrektywę ListDetailPaneScaffold
w ten sposób:
Użyj klasy, która reprezentuje treści do wybrania. Ta klasa powinna mieć wartość
Parcelable
, aby umożliwić zapisywanie i przywracanie wybranego elementu listy. Użyj wtyczki kotlin-parcelize, aby wygenerować kod.@Parcelize class MyItem(val id: Int) : Parcelable
Utwórz
ThreePaneScaffoldNavigator
za pomocąrememberListDetailPaneScaffoldNavigator
i dodajBackHandler
. Ten nawigator służy do przechodzenia między listą, panelem szczegółów i dodatkowymi panelami. Dzięki zadeklarowaniu typu ogólnego nawigator śledzi też stan rusztowania (czyli który elementMyItem
jest wyświetlany). Ponieważ ten typ jest parowalny, nawigator może zapisać i przywrócić stan, aby automatycznie obsługiwać zmiany konfiguracji.BackHandler
obsługuje nawigację wstecz za pomocą gestu lub przycisku systemowego. Oczekiwane działanie przycisku Wstecz wListDetailPaneScaffold
zależy od rozmiaru okna i bieżącej wartości szablonu. JeśliListDetailPaneScaffold
może wrócić do bieżącego stanu,canNavigateBack()
jesttrue
, co umożliwiaBackHandler
.val navigator = rememberListDetailPaneScaffoldNavigator<MyItem>() BackHandler(navigator.canNavigateBack()) { navigator.navigateBack() }
Przekazuj wartość
scaffoldState
z komponentunavigator
do komponentuListDetailPaneScaffold
.ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, // ... )
Przekaż implementację panelu list do
ListDetailPaneScaffold
. UżyjAnimatedPane
, aby zastosować domyślne animacje paneli podczas nawigacji. Następnie użyjThreePaneScaffoldNavigator
, aby przejść do panelu szczegółówListDetailPaneScaffoldRole.Detail
, i wyświetlić przekazany element.ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, listPane = { AnimatedPane { MyList( onItemClick = { item -> // Navigate to the detail pane with the passed item navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item) } ) } }, // ... )
W
ListDetailPaneScaffold
umieść implementację panelu szczegółów. Po zakończeniu nawigacjicurrentDestination
zawiera panel, do którego nawigowała aplikacja, w tym treści wyświetlane w tym panelu. Właściwośćcontent
ma ten sam typ, który został określony w pierwotnym wywołaniu funkcji remember (w tym przykładzie jest toMyItem
), więc możesz też uzyskać do niej dostęp, aby wyświetlić dowolne dane.ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, listPane = // ... detailPane = { AnimatedPane { navigator.currentDestination?.content?.let { MyDetails(it) } } }, )
Po wykonaniu powyższych czynności Twój kod powinien wyglądać mniej więcej tak:
val navigator = rememberListDetailPaneScaffoldNavigator<MyItem>() BackHandler(navigator.canNavigateBack()) { navigator.navigateBack() } ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, listPane = { AnimatedPane { MyList( onItemClick = { item -> // Navigate to the detail pane with the passed item navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item) }, ) } }, detailPane = { AnimatedPane { // Show the detail pane content if selected item is available navigator.currentDestination?.content?.let { MyDetails(it) } } }, )