As diretrizes de design de apps de TV definem uma variante de card
chamada "Wide classic card",
que mostra uma imagem e o bloco de conteúdo descritivo lado a lado.
Ao criar layouts bidimensionais complexos para telas de TV, o uso do posicionamento tradicional baseado em coordenadas ou contêineres Row e Column profundamente aninhados pode dificultar a leitura, a manutenção e a refatoração do código.
O Wide classic card é um caso de uso ideal para a API Grid do Jetpack Compose, ajudando a estruturar elementos lado a lado de maneira limpa usando áreas de layout 2D semânticas definidas pelo usuário.
Práticas recomendadas
Implemente o layout do card com Grid.
O uso do contêiner Grid melhora a legibilidade do código, desvinculando as dimensões do layout físico do posicionamento do item filho.
Em vez de depender de índices de faixa exatos, defina áreas semânticas nomeadas com a função area e coloque elementos combináveis filhos com o modificador gridItem.
Combine o dimensionamento de faixa flexível, como GridTrackSize.Auto
e minmax(0.dp, 1.fr),
com lacunas de faixa exatas (gap(row = 8.dp, column = 16.dp))
para organizar componentes de card complexos lado a lado de maneira clara e robusta.
Ingredientes
Grid: um layout de contêiner 2D no Jetpack Compose que organiza elementos combináveis filhos em linhas e colunas com base em uma lambda de configuraçãogridItem: uma extensãoModifierque associa um elemento de interface filho a umareaIdnomeado específico dentro de um layoutGridarea: uma função DSL de configuração emGridConfigurationScopeque mapeia umareaIdsemântico para intervalos ou intervalos de linha e coluna específicosCard: um elemento combinável de contêiner do Material Design que agrupa elementos de interface relacionados e estilosGridTrackSize.MinMax: uma propriedade de dimensionamento de faixa que define limites flexíveis (minemax) para dimensões de linha ou colunaGridTrackSize.Auto: uma propriedade de dimensionamento de faixa que dimensiona a faixa de linha ou coluna automaticamente para ajustar o conteúdo (column(GridTrackSize.Auto))gap: uma função de configuração que especifica o espaçamento vertical (row) e horizontal (column) entre as faixas da grade
Etapas
Defina identificadores de área, configure as faixas e áreas da grade e coloque os elementos combináveis filhos.
1. Definir identificadores de área semânticos
Primeiro, crie uma representação com segurança de tipo das regiões dentro do layout do Wide classic card. Uma classe enum evita erros de digitação de string e oferece segurança de tempo de compilação ao mapear faixas e colocar itens filhos.
enum class CardArea { Image, Title, Subtitle, Description, ExtraText, }
2. Configurar as faixas de grade 2D e as áreas nomeadas
Dentro da lambda config do elemento combinável Grid, defina as colunas e linhas que compõem a estrutura do card. Use GridTrackSize.Auto para a coluna de imagem para que ela envolva a largura da miniatura de maneira limpa. Use minmax(0.dp, 1.fr) para a coluna de conteúdo para que ela se expanda de maneira flexível na largura restante do card. Especifique o espaçamento da faixa com gap(row = 8.dp, column = 16.dp). Mapeie os identificadores CardArea para as coordenadas de faixa física usando a função 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. Colocar elementos combináveis filhos usando o modificador gridItem
Com as faixas e áreas configuradas, coloque cada elemento da interface filho puramente por intenção semântica usando o modificador gridItem. É possível declarar elementos combináveis filhos em qualquer ordem. O contêiner Grid posiciona cada elemento diretamente na região 2D atribuída automaticamente.
@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), ) } } }
Resultados
Ao organizar o Wide classic card com Grid e áreas nomeadas, você consegue uma separação limpa entre faixas de layout físico, coordenadas de área e posicionamento de elementos combináveis filhos.
Essa estrutura torna o layout legível e fácil de manter, seguindo as diretrizes de design de apps para TV para componentes de miniatura e descrição lado a lado.