Układ w pozycji na stole z użyciem siatki i zapytania o multimedia

Ikona oceny 4 gwiazdek

W przypadku urządzeń składanych w pozycji na stole pojedynczy ekran jest dzielony na 2 obszary wyświetlania oddzielone fizycznym zgięciem (lub zawiasem). W pozycji na stole główna zawartość aplikacji (np. odtwarzacz wideo lub obszar gry) znajduje się w górnej połowie, a elementy interaktywne (np. elementy sterujące multimediami lub pady) – w dolnej.

Urządzenie składane w pozycji stołowej, na którym na górnym ekranie wyświetlane są treści wideo, a na dolnym – elementy sterujące odtwarzaniem.
Rysunek 1. W pozycji na stole zawartość i elementy sterujące są rozdzielone fizycznym zgięciem.

Sprawdzone metody

Aby dodać do aplikacji obsługę pozycji na stole, użyj interfejsu Grid API, aby zdefiniować układ z 2 wierszami i 1 kolumną, i zastosuj zapytanie o media dotyczące pozycji na stole.

  • Reagowanie na pozycję na stole: użyj elementu mediaQuery, aby obserwować stan urządzenia. Gdy urządzenie jest złożone w pozycji na stole (windowPosture == Posture.Tabletop), możesz dynamicznie zmieniać układ bez konieczności ponownego uruchamiania aktywności lub złożonej obsługi cyklu życia.
  • Struktura układów za pomocą Grid: w pozycji na stole użyj interfejsu Grid API (2 rows, 1 column), aby wyraźnie oddzielić główną zawartość wizualną w górnym wierszu nad zgięciem od elementów sterujących w dolnym wierszu pod zgięciem.
  • Wykorzystanie domyślnego indeksowania Z w przypadku nakładek: w standardowych pozycjach (innych niż na stole) przypisz do tej samej komórki kilka identyfikatorów obszarów, aby nałożyć elementy sterujące na odtwarzacz. Grid automatycznie renderuje elementy od tyłu do przodu w kolejności ich deklaracji.
  • Płynne przejścia: zadbaj o to, aby stan i pozycje przewijania były zachowywane podczas przechodzenia między standardowymi układami pełnoekranowymi a pozycją na stole.

Składniki

  • Grid: adaptacyjny kontener układu, który umożliwia umieszczanie elementów w konfigurowalnych wierszach i kolumnach. Idealnie nadaje się do dzielenia treści na różne obszary ekranu.
  • mediaQuery: interfejs Jetpack Compose API służący do bezpośredniego sprawdzania w elementach kompozycyjnych bieżącej pozycji okna aplikacji, klas rozmiarów i charakterystyki sprzętu.

Kroki

Sprawdź stan zabezpieczeń urządzenia za pomocą mediaQuery(). Gdy urządzenie jest w pozycji na stole, ułóż zawartość aplikacji w siatce pionowej z 2 wierszami i 1 kolumną, tak aby główna zawartość znajdowała się u góry, a elementy sterujące były dostępne u dołu.

1. Określ konfiguracje siatki w trybie na stole

W funkcji typu „composable” zdefiniuj identyfikatory obszarów układu za pomocą typu wyliczeniowego i skonfiguruj bloki GridConfigurationScope dla pozycji domyślnej i na stole.

W defaultConfig oba obszary są przypisane do tej samej komórki (row = 1, column = 1). Grid używa domyślnego indeksowania Z, w którym elementy kompozycyjne zadeklarowane później w układzie są renderowane na wierzchu wcześniejszych, co pozwala kontrolerowi nakładać się na odtwarzacz bez dodatkowego zagnieżdżania kontenerów (więcej informacji znajdziesz w artykule Nakładanie elementów interfejsu za pomocą siatki).

enum class VideoPlayerArea { Player, Controller }

object PlayerGridConfig {
    // Default: Single area layout with overlay (controls on top of player)
    val defaultConfig: GridConfigurationScope.() -> Unit = {
        row(1f)
        column(1f)
        area(areaId = VideoPlayerArea.Player, row = 1, column = 1)
        area(areaId = VideoPlayerArea.Controller, row = 1, column = 1)
    }

    // Tabletop: Two rows splitting content across the fold
    val tabletopConfig: GridConfigurationScope.() -> Unit = {
        row(0.5f)
        row(0.5f)
        column(1f)
        area(areaId = VideoPlayerArea.Player, row = 1, column = 1) // Top half above fold
        area(areaId = VideoPlayerArea.Controller, row = 2, column = 1) // Bottom half below fold
    }
}

2. Wykryj pozycję na stole i zastosuj konfigurację do siatki

Użyj mediaQuery, aby wybrać aktywną konfigurację na podstawie windowPosture, przekaż config do Grid i powiąż zawartość kompozycyjną z identyfikatorami obszarów. Zadeklarowanie VideoPlayerArea.Player przed VideoPlayerArea.Controller sprawia, że gdy oba elementy współdzielą komórkę w defaultConfig, elementy sterujące są renderowane nad odtwarzaczem:

val config = mediaQuery {
    when (windowPosture) {
        Posture.Tabletop -> PlayerGridConfig.tabletopConfig
        else -> PlayerGridConfig.defaultConfig
    }
}

Grid(config = config) {
    Box(
        modifier = Modifier
            .gridItem(areaId = VideoPlayerArea.Player)
    ) {
        // VideoPlayerContent
    }

    Box(
        modifier = Modifier
            .gridItem(areaId = VideoPlayerArea.Controller)
    ) {
        // PlaybackControlsContent
    }
}

Wyniki

Dzięki połączeniu mediaQuery i Grid aplikacja dynamicznie wykrywa, kiedy urządzenie składane jest częściowo złożone w pozycji na stole, i automatycznie dostosowuje interfejs do 2 obszarów wyświetlania oddzielonych zgięciem.

Dodatkowe materiały