Szeroki klasyczny układ karty z siatką

Ikona oceny czterech gwiazdek

Wytyczne dotyczące projektowania aplikacji TV określają wariant karty o nazwie „Szeroka karta klasyczna”, która wyświetla obraz i blok treści opisowych obok siebie. Podczas tworzenia złożonych układów dwuwymiarowych na ekrany telewizorów używanie tradycyjnego pozycjonowania opartego na współrzędnych lub głęboko zagnieżdżonych kontenerów Row i Column może utrudnić odczytywanie, utrzymywanie i refaktoryzację kodu. Szeroka karta klasyczna to idealny przypadek użycia interfejsu Jetpack Compose Grid, który pomaga w przejrzystym strukturyzowaniu elementów obok siebie za pomocą semantycznych, zdefiniowanych przez użytkownika obszarów układu 2D.

Specyfikacja komponentu karty klasycznej w wersji szerokiej z 5 obszarami układu: Obraz, Tytuł, Podtytuł, Opis i Dodatkowy tekst.
Rysunek 1. Szeroka karta klasyczna z 5 nazwanymi obszarami: obszar obrazu i 4 obszary tekstowe w bloku treści.

Sprawdzone metody

Zaimplementuj układ karty za pomocą Grid. Użycie kontenera Grid poprawia czytelność kodu, ponieważ oddziela fizyczne wymiary układu od umieszczenia elementów podrzędnych. Zamiast polegać na dokładnych indeksach ścieżek, zdefiniuj semantyczne nazwane obszary za pomocą funkcji area i umieść elementy podrzędne za pomocą modyfikatora gridItem. Połącz elastyczne rozmiary ścieżek, takie jak GridTrackSize.Auto i minmax(0.dp, 1.fr), z dokładnymi odstępami między ścieżkami (gap(row = 8.dp, column = 16.dp)) aby przejrzyście i niezawodnie uporządkować złożone komponenty karty obok siebie.

Składniki

  • Grid: układ kontenera 2D w Jetpack Compose, który rozmieszcza elementy podrzędne w wierszach i kolumnach na podstawie lambdy konfiguracji.
  • gridItem: rozszerzenie Modifier, które łączy podrzędny element interfejsu z konkretnym nazwanym areaId w układzie Grid.
  • area: funkcja DSL konfiguracji w GridConfigurationScope, która mapuje semantyczny areaId na konkretne zakresy lub przedziały wierszy i kolumn.
  • Card: komponent kontenera Material Design, który grupuje powiązane elementy interfejsu i style.
  • GridTrackSize.MinMax: właściwość rozmiaru ścieżki, która określa elastyczne granice (min i max) wymiarów wiersza lub kolumny.
  • GridTrackSize.Auto: właściwość rozmiaru ścieżki, która automatycznie dopasowuje rozmiar wiersza lub kolumny ścieżki do jego zawartości (column(GridTrackSize.Auto)).
  • gap: funkcja konfiguracji, która określa pionowe (row) i poziome (column) odstępy między ścieżkami siatki.

Kroki

Zdefiniuj identyfikatory obszarów, skonfiguruj ścieżki i obszary siatki, a następnie umieść elementy podrzędne.

1. Zdefiniuj semantyczne identyfikatory obszarów

Najpierw utwórz bezpieczną pod względem typów reprezentację regionów w układzie szerokiej karty klasycznej. Klasa enum pozwala uniknąć błędów w ciągach znaków i zapewnia bezpieczeństwo w czasie kompilacji podczas mapowania ścieżek i umieszczania elementów podrzędnych.

enum class CardArea {
    Image,
    Title,
    Subtitle,
    Description,
    ExtraText,
}

2. Skonfiguruj ścieżki siatki 2D i nazwane obszary

W lambdzie config komponentu Grid zdefiniuj kolumny i wiersze, które tworzą strukturę karty. Użyj GridTrackSize.Auto w przypadku kolumny obrazu, aby dopasować ją do szerokości miniatury. Użyj minmax(0.dp, 1.fr) w przypadku kolumny treści, aby elastycznie rozszerzać ją na pozostałą szerokość karty. Określ odstępy między ścieżkami za pomocą gap(row = 8.dp, column = 16.dp). Zmapuj identyfikatory CardArea na ich fizyczne współrzędne ścieżek za pomocą funkcji area.

Grid(
    config = {
        // Define columns: left column for image, right for content
        column(GridTrackSize.Auto)
        column(minmax(0.dp, 1.fr))

        // Define row tracks for the vertical content stack
        row(GridTrackSize.Auto)
        row(GridTrackSize.Auto)
        row(GridTrackSize.Auto)
        row(GridTrackSize.Auto)

        // Map semantic identifiers to grid coordinates and spans
        area(CardArea.Image, row = 1, column = 1, rowSpan = 4)
        area(CardArea.Title, row = 1, column = 2)
        area(CardArea.Subtitle, row = 2, column = 2)
        area(CardArea.Description, row = 3, column = 2)
        area(CardArea.ExtraText, row = 4, column = 2)

        gap(row = 8.dp, column = 16.dp)
    }
) {
    // Child elements placed in Step 3
}

3. Umieść elementy podrzędne za pomocą modyfikatora gridItem

Po skonfigurowaniu ścieżek i obszarów umieść każdy podrzędny element interfejsu wyłącznie na podstawie semantycznego zamiaru za pomocą modyfikatora gridItem. Elementy podrzędne możesz deklarować w dowolnej kolejności. Kontener Grid automatycznie umieszcza każdy element bezpośrednio w przypisanym mu regionie 2D.

@Composable
fun WideClassicCard(
    imageContent: @Composable () -> Unit,
    title: String,
    subtitle: String,
    description: String,
    extraText: String,
    modifier: Modifier = Modifier,
) {
    Card(modifier = modifier) {
        Grid(
            config = {
                // Define columns: left column for image, right for content
                column(GridTrackSize.Auto)
                column(minmax(0.dp, 1.fr))

                // Define row tracks for the vertical content stack
                row(GridTrackSize.Auto)
                row(GridTrackSize.Auto)
                row(GridTrackSize.Auto)
                row(GridTrackSize.Auto)

                // Map semantic identifiers to grid coordinates and spans
                area(CardArea.Image, row = 1, column = 1, rowSpan = 4)
                area(CardArea.Title, row = 1, column = 2)
                area(CardArea.Subtitle, row = 2, column = 2)
                area(CardArea.Description, row = 3, column = 2)
                area(CardArea.ExtraText, row = 4, column = 2)

                gap(row = 8.dp, column = 16.dp)
            },
        ) {
            Box(modifier = Modifier.gridItem(CardArea.Image)) {
                imageContent()
            }
            Text(
                text = title,
                style = MaterialTheme.typography.titleLarge,
                modifier = Modifier
                    .gridItem(CardArea.Title)
                    .padding(top = 16.dp, end = 16.dp),
            )

            Text(
                text = subtitle,
                style = MaterialTheme.typography.titleMedium,
                modifier = Modifier
                    .gridItem(CardArea.Subtitle)
                    .padding(end = 16.dp),
            )

            Text(
                text = description,
                style = MaterialTheme.typography.bodyMedium,
                modifier = Modifier
                    .gridItem(CardArea.Description)
                    .padding(end = 16.dp),
            )

            Text(
                text = extraText,
                style = MaterialTheme.typography.labelSmall,
                modifier = Modifier
                    .gridItem(CardArea.ExtraText)
                    .padding(bottom = 16.dp, end = 16.dp),
            )
        }
    }
}

Wyniki

Dzięki uporządkowaniu szerokiej karty klasycznej za pomocą Grid i nazwanych obszarów uzyskasz wyraźne rozdzielenie fizycznych ścieżek układu, współrzędnych obszarów i umieszczenia elementów podrzędnych. Ta struktura sprawia, że układ jest czytelny i łatwy w utrzymaniu, a jednocześnie jest zgodny z wytycznymi dotyczącymi projektowania aplikacji TV w przypadku komponentów miniatury i opisu obok siebie.

Dodatkowe materiały