Los lineamientos de diseño de la app para TV definen una variante de tarjeta
llamada tarjeta clásica ancha,
que muestra una imagen y su bloque de contenido descriptivo uno al lado del otro.
Cuando compilas diseños bidimensionales complejos para pantallas de TV, el uso del posicionamiento tradicional basado en coordenadas o los contenedores Row y Column anidados en profundidad pueden dificultar la lectura, el mantenimiento y la refactorización del código.
La tarjeta clásica ancha es un caso de uso ideal para la API de Grid de Jetpack Compose, que te ayuda a estructurar elementos uno al lado del otro de forma clara con áreas de diseño semánticas y bidimensionales definidas por el usuario.
Prácticas recomendadas
Implementa el diseño de la tarjeta con Grid.
El uso del contenedor Grid mejora la legibilidad del código, ya que desacopla las dimensiones del diseño físico de la ubicación del elemento secundario.
En lugar de depender de los índices de seguimiento exactos, define áreas semánticas con nombre con la función area y coloca elementos componibles secundarios con el modificador gridItem.
Combina el tamaño flexible de seguimiento, como GridTrackSize.Auto
y minmax(0.dp, 1.fr),
con espacios de seguimiento exactos (gap(row = 8.dp, column = 16.dp))
para organizar componentes de tarjetas complejos uno al lado del otro de forma clara y sólida.
Ingredientes
Grid: Un diseño de contenedor 2D en Jetpack Compose que organiza elementos componibles secundarios en filas y columnas según una expresión lambda de configuracióngridItem: Una extensiónModifierque asocia un elemento de la IU secundario con unareaIdcon nombre específico dentro de un diseñoGridarea: Una función DSL de configuración dentro deGridConfigurationScopeque asigna unareaIdsemántico a rangos o intervalos de filas y columnas específicosCard: Un elemento componible de contenedor de Material Design que agrupa elementos de la IU y estilos relacionadosGridTrackSize.MinMax: Una propiedad de tamaño de seguimiento que define límites flexibles (minymax) para las dimensiones de filas o columnasGridTrackSize.Auto: Una propiedad de tamaño de seguimiento que ajusta automáticamente el tamaño del seguimiento de filas o columnas para que se ajuste a su contenido (column(GridTrackSize.Auto))gap: Una función de configuración que especifica el espaciado vertical (row) y horizontal (column) entre los seguimientos de la cuadrícula
Pasos
Define los identificadores de área, configura los seguimientos y las áreas de la cuadrícula y, luego, coloca los elementos componibles secundarios.
1. Define identificadores de área semánticos
Primero, crea una representación con seguridad de tipos de las regiones dentro del diseño de la tarjeta clásica ancha. Una clase enum evita errores tipográficos de cadenas y proporciona seguridad en tiempo de compilación cuando se asignan seguimientos y se colocan elementos secundarios.
enum class CardArea { Image, Title, Subtitle, Description, ExtraText, }
2. Configura los seguimientos y las áreas con nombre de la cuadrícula 2D
Dentro de la expresión lambda config del elemento componible Grid, define las columnas y las filas que componen la estructura de la tarjeta. Usa GridTrackSize.Auto para la columna de la imagen de modo que ajuste el ancho de la miniatura de forma clara. Usa minmax(0.dp, 1.fr) para la columna de contenido de modo que se expanda de forma flexible en el ancho restante de la tarjeta. Especifica el espaciado de seguimiento con gap(row = 8.dp, column = 16.dp). Asigna tus identificadores CardArea a sus coordenadas de seguimiento físicas con la función 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. Coloca elementos componibles secundarios con el modificador gridItem
Con los seguimientos y las áreas configurados, coloca cada elemento de la IU secundario únicamente por intención semántica con el modificador gridItem. Puedes declarar elementos componibles secundarios en cualquier orden. El contenedor Grid posiciona cada elemento directamente en su región 2D asignada de forma automática.
@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
Si organizas tu tarjeta clásica ancha con Grid y áreas con nombre, lograrás una separación clara entre los seguimientos de diseño físico, las coordenadas de área y la ubicación de elementos componibles secundarios.
Esta estructura hace que tu diseño sea legible y fácil de mantener, a la vez que sigue los lineamientos de diseño de la app para TV para los componentes de miniatura y descripción uno al lado del otro.
Recursos adicionales
- Lineamientos de diseño para TV: Tarjetas
- Guía de apps adaptables: Propiedades del contenedor de cuadrícula