Tworzenie układu ze szczegółami listy

Lista i szczegóły to wzorzec interfejsu, który składa się z układu z 2 panelami, gdzie jeden panel przedstawia listę elementów, a drugi wyświetla szczegóły elementów wybranych z listy.

Wzorzec jest szczególnie przydatny w przypadku aplikacji, które dostarczają szczegółowych informacji o elementach dużych kolekcji, np. klienta poczty e-mail, który zawiera listę e-maili i szczegółową treść każdej wiadomości. Szczegółowa lista może być też używana w przypadku mniej istotnych ścieżek, np. do dzielenia ustawień aplikacji na listę kategorii z ustawieniami dla każdej kategorii w okienku szczegółów.

Okienko szczegółów wyświetlane obok strony z listą.
Rysunek 1. Jeśli rozmiar ekranu jest wystarczający, okienko szczegółów jest wyświetlane obok okienka listy.
Po wybraniu elementu okienko szczegółów zajmuje cały ekran.
Rysunek 2. Gdy rozmiar ekranu jest ograniczony, okienko szczegółów (po wybraniu elementu) zajmuje całą przestrzeń.

Implementowanie wzorca szczegółowa lista za pomocą NavigableListDetailPaneScaffold

NavigableListDetailPaneScaffold to funkcja kompozycyjna, która upraszcza implementację układu szczegółowej listy w Jetpack Compose. Zawiera on element ListDetailPaneScaffold i dodaje wbudowaną nawigację oraz animacje przewidywanego przejścia wstecz.

Szkielet szczegółowej listy obsługuje maksymalnie 3 panele:

  1. Panel listy: wyświetla kolekcję elementów.
  2. Okienko szczegółów: pokazuje szczegóły wybranego elementu.
  3. Dodatkowy panel (opcjonalny): zapewnia dodatkowy kontekst, gdy jest to potrzebne.

Szkielet dostosowuje się do rozmiaru okna:

  • W dużych oknach lista i okienko szczegółów są wyświetlane obok siebie.
  • W małych oknach widoczny jest tylko jeden panel naraz, który zmienia się, gdy użytkownicy przechodzą do innych sekcji.

Deklarowanie zależności

NavigableListDetailPaneScaffold jest częścią biblioteki nawigacji adaptacyjnej Material 3.

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")

Dynamiczny

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 i Posture;
  • adaptive-layout: układy adaptacyjne, takie jak ListDetailPaneScaffold i SupportingPaneScaffold
  • adaptive-navigation: elementy kompozycyjne do poruszania się w obrębie paneli i między nimi, a także układy adaptacyjne, które domyślnie obsługują nawigację, takie jak NavigableListDetailPaneScaffold i NavigableSupportingPaneScaffold

Upewnij się, że Twój projekt zawiera 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 na 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 poszczególnych tagów <activity> w pliku AndroidManifest.xml. Więcej informacji znajdziesz w artykule Włączanie gestu przewidywanego przejścia wstecz.

Gdy aplikacja jest kierowana na Androida 16 (API na poziomie 36) lub nowszego, przewidywane przejście wstecz jest domyślnie włączone.

Podstawowe użycie

Zaimplementuj NavigableListDetailPaneScaffold w ten sposób:

  1. Użyj klasy, która reprezentuje wybrane treści. Użyj klasy Parcelable, aby umożliwić zapisywanie i przywracanie wybranego elementu listy. Użyj wtyczki kotlin-parcelize, aby wygenerować kod.
  2. Utwórz ThreePaneScaffoldNavigator za pomocą rememberListDetailPaneScaffoldNavigator.

Ten nawigator służy do przechodzenia między listą, szczegółami i dodatkowymi panelami. Dzięki zadeklarowaniu typu ogólnego nawigator śledzi też stan rusztowania (czyli to, który element MyItem jest wyświetlany). Ponieważ ten typ jest możliwy do spakowania, stan może zostać zapisany i przywrócony przez nawigator, aby automatycznie obsługiwać zmiany konfiguracji.

  1. Przekaż nawigator do funkcji kompozycyjnej NavigableListDetailPaneScaffold.

  2. Przekaż implementację panelu listy do NavigableListDetailPaneScaffold. Użyj AnimatedPane, aby zastosować domyślne animacje panelu podczas nawigacji. Następnie użyj ThreePaneScaffoldNavigator, aby przejść do okienka szczegółów, ListDetailPaneScaffoldRole.Detail, i wyświetlić przekazany element.

  3. Uwzględnij implementację okienka szczegółów w pliku NavigableListDetailPaneScaffold.

Po zakończeniu nawigacji currentDestination zawiera panel, do którego aplikacja przeszła, w tym treści wyświetlane w panelu. Właściwość contentKey jest tego samego typu co określona w pierwotnym wywołaniu, więc możesz uzyskać dostęp do wszystkich danych, które chcesz wyświetlić.

  1. Opcjonalnie możesz zmienić defaultBackBehavior w pliku NavigableListDetailPaneScaffold. Domyślnie NavigableListDetailPaneScaffold używa PopUntilScaffoldValueChange dla defaultBackBehavior.

Jeśli aplikacja wymaga innego wzorca przechodzenia wstecz, możesz zastąpić to zachowanie, określając inną opcję BackNavigationBehavior.

BackNavigationBehavior opcji

W tej sekcji używamy przykładu aplikacji do poczty e-mail z listą e-maili w jednym panelu i widokiem szczegółowym w drugim.

To zachowanie dotyczy zmian w ogólnej strukturze układu. W konfiguracji z wieloma panelami zmiana treści e-maila w okienku szczegółów nie zmienia podstawowej struktury układu. Dlatego przycisk Wstecz może spowodować zamknięcie aplikacji lub bieżącego wykresu nawigacji, ponieważ w bieżącym kontekście nie ma żadnej zmiany układu, którą można by cofnąć. W układzie z jednym panelem naciśnięcie przycisku Wstecz spowoduje pominięcie zmian treści w widoku szczegółowym i powrót do widoku listy, ponieważ oznacza to wyraźną zmianę układu.

Rozważ te przykłady:

  • Wiele paneli: wyświetlasz e-maila (element 1) w okienku szczegółów. Kliknięcie innego e-maila (element 2) powoduje zaktualizowanie okienka szczegółów, ale okienka listy i szczegółów pozostają widoczne. Naciśnięcie przycisku Wstecz może spowodować zamknięcie aplikacji lub bieżącego procesu nawigacji.
  • Pojedynczy panel: wyświetlasz element 1, a następnie element 2. Naciśnięcie przycisku Wstecz spowoduje powrót bezpośrednio do panelu listy e-maili.

Używaj tej opcji, gdy chcesz, aby użytkownicy widzieli wyraźne przejścia układu przy każdym działaniu wstecz.

Ilustracja przedstawiająca zmiany wartości nawigacji w różnych panelach układu.
PopUntilContentChange

To zachowanie nadaje priorytet wyświetlanym treściom. Jeśli wyświetlisz element 1, a następnie element 2, naciśnięcie przycisku Wstecz spowoduje powrót do elementu 1, niezależnie od układu.

Rozważ te przykłady:

  • Wiele paneli: wyświetlasz element 1 w okienku szczegółów, a następnie klikasz element 2 na liście. Okienko szczegółów zostanie zaktualizowane. Naciśnięcie przycisku Wstecz spowoduje przywrócenie okienka szczegółów do elementu 1.
  • Pojedynczy panel: następuje przywrócenie tej samej treści.

Używaj tego, gdy użytkownik oczekuje, że po kliknięciu przycisku Wstecz wróci do wcześniej wyświetlanych treści.

przejście między 2 okienkami szczegółów,
PopUntilCurrentDestinationChange

To działanie powoduje wyskakiwanie stosu wstecznego do momentu zmiany bieżącego miejsca docelowego nawigacji. Dotyczy to zarówno układów z jednym panelem, jak i z wieloma panelami.

Rozważ te przykłady:

Niezależnie od tego, czy korzystasz z układu z jednym czy wieloma panelami, naciśnięcie przycisku Wstecz zawsze przeniesie zaznaczenie z podświetlonego elementu nawigacyjnego do poprzedniego miejsca docelowego. W naszej aplikacji do poczty e-mail oznacza to, że wizualne oznaczenie wybranego panelu zostanie przesunięte.

Używaj tego, gdy utrzymanie wyraźnego wizualnego wskazania bieżącej nawigacji jest kluczowe dla wygody użytkownika.

poruszanie się między panelami szczegółów i listy,
PopLatest

Ta opcja usuwa ze stosu tylko ostatnie miejsce docelowe. Użyj tej opcji, aby przechodzić wstecz bez pomijania stanów pośrednich.

Po wykonaniu tych czynności kod powinien wyglądać mniej więcej tak:

NavigableListDetailPaneScaffold(
    navigator = navigator,
    listPane = {
        AnimatedPane {
            ListContent(
                words = sampleWords,
                selectionState = navigator.currentDestination?.contentKey?.let {
                    SelectionVisibilityState.ShowSelection(it)
                } ?: SelectionVisibilityState.NoSelection,
                onWordClick = { word ->
                    scope.launch {
                        navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, word)
                    }
                },
                animatedVisibilityScope = this@AnimatedPane,
                sharedTransitionScope = this@SharedTransitionLayout
            )
        }
    },
    detailPane = {
        AnimatedPane {
            DetailContent(
                definedWord = navigator.currentDestination?.contentKey,
                animatedVisibilityScope = this@AnimatedPane,
                sharedTransitionScope = this@SharedTransitionLayout,
                onClosePane = {
                    scope.launch {
                        navigator.navigateBack(
                            backNavigationBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange
                        )

                    }
                }
            )
        }
    }