Широкая классическая карточная разметка с сеткой.

значок четырехзвездочного рейтинга

В рекомендациях по дизайну приложений для телевизоров описан вариант карточки, называемый « Широкая классическая карточка» , которая отображает изображение и блок с его описанием рядом друг с другом. При создании сложных двухмерных макетов для экранов телевизоров использование традиционного позиционирования на основе координат или глубоко вложенных контейнеров Row и Column может затруднить чтение, сопровождение и рефакторинг кода. «Широкая классическая карточка» — идеальный пример использования API Jetpack Compose Grid , помогающий аккуратно структурировать элементы, расположенные рядом, с помощью семантических, определяемых пользователем двухмерных областей макета.

Спецификация компонента «Широкая классическая карточка», демонстрирующая пять именованных областей макета: Изображение, Заголовок, Подзаголовок, Описание и Дополнительный текст.
Рисунок 1. Широкая классическая карточка с пятью именованными областями: область изображения и четыре текстовые области в блоке содержимого.

Передовые методы

Реализуйте компоновку карточек с помощью Grid . Использование контейнера Grid повышает читаемость кода, отделяя физические размеры компоновки от размещения дочерних элементов. Вместо того чтобы полагаться на точные индексы дорожек, определите семантически именованные области с помощью функции area и разместите дочерние элементы с помощью модификатора gridItem . Сочетайте гибкое определение размеров дорожек, например GridTrackSize.Auto и minmax(0.dp, 1.fr) , с точными промежутками между дорожками ( gap(row = 8.dp, column = 16.dp) ) для четкой и надежной организации сложных компонентов карточек, расположенных рядом друг с другом.

Ингредиенты

  • Grid : Двумерная компоновка контейнера в Jetpack Compose, которая располагает дочерние элементы в строки и столбцы на основе лямбда-функции конфигурации.
  • gridItem : расширение Modifier , связывающее дочерний элемент пользовательского интерфейса с определенным именованным areaId внутри макета Grid
  • area : Функция DSL конфигурации в рамках GridConfigurationScope , которая сопоставляет семантический areaId с определенными диапазонами строк и столбцов.
  • Card : Контейнер в стиле Material Design, объединяющий связанные элементы пользовательского интерфейса и стили.
  • GridTrackSize.MinMax : Свойство размера дорожки, определяющее гибкие границы ( min и max ) для размеров строк или столбцов.
  • GridTrackSize.Auto : Свойство, определяющее размер дорожки, автоматически подстраивающее её под содержимое строки или столбца ( column(GridTrackSize.Auto) )
  • gap : Функция конфигурации, определяющая вертикальное ( row ) и горизонтальное ( column ) расстояние между дорожками сетки.

Шаги

Определите идентификаторы областей, настройте сетки и области, затем разместите дочерние элементы, которые можно комбинировать.

1. Определите идентификаторы семантических областей.

Во-первых, создайте типобезопасное представление регионов внутри вашей классической широкоформатной схемы расположения карт. Класс enum позволяет избежать опечаток в строках и обеспечивает безопасность на этапе компиляции при сопоставлении дорожек и размещении дочерних элементов.

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

2. Настройте двухмерную сетку дорожек и именованные области.

В лямбда- config вашего составного элемента Grid определите столбцы и строки, составляющие структуру карточки. Используйте GridTrackSize.Auto для столбца изображений, чтобы он корректно переносился на ширину миниатюры. Используйте minmax(0.dp, 1.fr) для столбца содержимого, чтобы он гибко расширялся на оставшуюся ширину карточки. Укажите межстрочный интервал с помощью gap(row = 8.dp, column = 16.dp) . Сопоставьте идентификаторы CardArea с их физическими координатами дорожки, используя функцию 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. Размещайте дочерние элементы, используя модификатор gridItem.

После настройки дорожек и областей разместите каждый дочерний элемент пользовательского интерфейса, руководствуясь исключительно семантическим принципом, используя модификатор gridItem . Вы можете объявлять дочерние элементы в любом порядке. Контейнер Grid автоматически размещает каждый элемент непосредственно в назначенной ему 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),
            )
        }
    }
}

Результаты

Организуя классическую широкую карточку с помощью Grid и именованных областей, вы добиваетесь четкого разделения между физическими дорожками макета, координатами областей и размещением дочерних элементов. Такая структура делает ваш макет читаемым и удобным для сопровождения, а также соответствует рекомендациям по дизайну приложений для ТВ, предусматривающим размещение рядом миниатюр и описаний.

Дополнительные ресурсы