Tworzenie układu ze szczegółami listy

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. Szczegółów listy można też używać w przypadku mniej krytycznych ścieżek, takich jak dzielenie aplikacji swoje preferencje na liście kategorii z preferencjami dla każdej z nich panelu szczegółów.

Zaimplementuj wzorzec interfejsu za pomocą interfejsu 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łym ekranie rusztowanie automatycznie przełączy się na wyświetlanie listy lub panelu szczegółów na pełnym ekranie.

Okienko szczegółów widoczne obok strony z listą.
Rysunek 1. Gdy dostępny jest wystarczający rozmiar ekranu, szczegóły widoczny obok okienka z listą.
.
Po wybraniu elementu panel szczegółów zajmie cały ekran.
Rys. 2. Gdy rozmiar ekranu jest ograniczony, panel szczegółów (po wybraniu elementu) zajmuje całą przestrzeń.

Deklarowanie zależności

ListDetailPaneScaffold jest częścią układu adaptacyjnego Material 3

Dodaj te 3 powiązane zależności do pliku build.gradle swojego aplikacja lub moduł:

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 – podstawowe elementy składowe, takie jak HingeInfo i Posture
  • układ adaptacyjny – układy adaptacyjne, takie jak ListDetailPaneScaffold i SupportingPaneScaffold
  • adaptive-Navigation – elementy kompozycyjne do nawigacji w obrębie między panelami

Podstawowe użycie

Zaimplementuj dyrektywę ListDetailPaneScaffold w ten sposób:

  1. Użyj zajęć, które odpowiadają treściom, które chcesz wybrać. Ta klasa powinna mieć wartość Parcelable, aby umożliwić zapisywanie i przywracanie wybranego elementu listy. Wykorzystaj „parcelize” kotlin wtyczki, by wygenerować kod.

    @Parcelize
    class MyItem(val id: Int) : Parcelable

  2. Utwórz ThreePaneScaffoldNavigator za pomocą rememberListDetailPaneScaffoldNavigator i dodaj BackHandler. Ten nawigator służy do poruszania się między listą, szczegółami i dodatkowymi panelami. Według zadeklarując typ ogólny, nawigator śledzi również stan scaffold (czyli wyświetlane jest MyItem). Ponieważ ten typ jest parowalny, stan może być zapisywany i przywracany przez nawigatora, aby automatycznie obsługiwać zmiany konfiguracji. BackHandler obsługuje nawigację wstecz za pomocą gestu lub przycisku systemowego. Oczekiwane działanie przycisku Wstecz w ListDetailPaneScaffold zależy od rozmiaru okna i bieżącej wartości szablonu. Jeśli ListDetailPaneScaffold może wrócić do bieżącego stanu, canNavigateBack() jest true, co umożliwia BackHandler.

    val navigator = rememberListDetailPaneScaffoldNavigator<MyItem>()
    
    BackHandler(navigator.canNavigateBack()) {
        navigator.navigateBack()
    }

  3. Przekaż scaffoldState z przystanku navigator do ListDetailPaneScaffold kompozycyjne.

    ListDetailPaneScaffold(
        directive = navigator.scaffoldDirective,
        value = navigator.scaffoldValue,
        // ...
    )

  4. Udostępnij w narzędziu ListDetailPaneScaffold implementację panelu listy. Użyj AnimatedPane aby zastosować domyślne animacje panelu podczas nawigacji. Następnie użyj ThreePaneScaffoldNavigator, aby przejść do panelu szczegółów. ListDetailPaneScaffoldRole.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)
                    }
                )
            }
        },
        // ...
    )

  5. Dołącz wdrożenie panelu szczegółów w narzędziu ListDetailPaneScaffold. Po zakończeniu nawigacji currentDestination będzie zawierać panel Do której udało się przejść aplikację, w tym do treści wyświetlanej w 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 to MyItem), 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)
            }
        }
    },
)