Listas diferidas en una cuadrícula

Ícono de calificación de cuatro estrellas

El elemento componible Grid crea diseños de pantalla estructurales y bidimensionales. Grid define una estructura de diseño responsivo con pistas (filas y columnas) y espacios definidos de forma explícita como la arquitectura fundamental de tu IU.

Debido a que Grid es un contenedor estructural y no de carga diferida, requiere que definas de forma explícita cada elemento que se coloca en él sin reciclar elementos en el desplazamiento. Como resultado, renderizar conjuntos de datos grandes o dinámicos directamente dentro de un Grid puede causar cuellos de botella en el rendimiento, ya que todos los elementos se componen de forma simultánea.

Para mostrar grandes colecciones de datos en un diseño de pantalla estructurado, incorpora componentes diferidos, como LazyColumn o LazyRow, en tus celdas de Grid. Sin embargo, ten en cuenta que las pistas flexibles (con especificaciones como 1.fr) consultan los tamaños intrínsecos de los elementos secundarios. Debido a que SubcomposeLayout no admite pases de medición intrínsecos, colocar una lista diferida dentro de una pista flexible provoca una falla de IllegalStateException. Para colocar listas diferidas de forma segura dentro de una pista de cuadrícula flexible, debes usar el tamaño GridTrackSize.MinMax (como minmax(0.dp, 1.fr)) para omitir el pase de medición intrínseco.

Diseño de pantalla con un encabezado superior, una lista desplazable de elementos en el área de contenido principal y un pie de página inferior.
Figura 1: Diseño de pantalla estructural con un encabezado, un pie de página y un LazyColumn incorporado para el contenido.

Prácticas recomendadas

  • Usa listas diferidas en lugar de bucles explícitos grandes: Para mostrar conjuntos de datos grandes o dinámicos dentro de un Grid estructurado, incorpora componentes diferidos (por lo general, LazyColumn o LazyRow) dentro de celdas de cuadrícula específicas en lugar de crear bucles explícitos grandes sobre los elementos, ya que Grid no recicla elementos y tiene un límite de 1,000 pistas.
  • Usa el tamaño de pista MinMax para las listas diferidas: Como LazyColumn y LazyRow no admiten pases de medición intrínsecos (consulta SubcomposeLayout), usa GridTrackSize.MinMax en pistas flexibles que alojan componentes diferidos para omitir las mediciones intrínsecas de forma segura.

Ingredientes

  • Grid: Es un diseño de elemento componible que coloca elementos en una estructura de cuadrícula bidimensional configurada con pistas de filas y columnas explícitas.
  • LazyColumn: Es una lista de desplazamiento vertical que compone y recicla solo los elementos visibles en la pantalla.
  • GridTrackSize.MinMax: Es la propiedad de tamaño de la pista que define límites flexibles (min y max) para alojar de forma segura componentes diferidos sin activar fallas de medición del tiempo de ejecución.
  • gridItem: Es la extensión de Compose Modifier que asigna un elemento de la IU secundario a una celda específica o un área con nombre dentro de un Grid.

Pasos

Estructura el diseño de tu pantalla definiendo identificadores de áreas semánticas, configurando pistas de cuadrícula con el tamaño minmax para la compatibilidad con listas diferidas y, luego, incorporando LazyColumn dentro del área de contenido de la cuadrícula.

1. Configura pistas de cuadrícula y áreas con nombre

Crea una clase enum para representar las distintas regiones del diseño de tu pantalla y define una lambda GridConfigurationScope para las pistas de diseño y las áreas con nombre. Usa GridTrackSize.MaxContent para que las filas del encabezado y el pie de página se ajusten a las dimensiones de su contenido, y usa minmax(0.dp, 1.fr) para la pista de contenido que aloja la lista diferida para asignar espacio flexible sin consultar mediciones intrínsecas no admitidas:

enum class ScreenArea {
    Header,
    Content,
    Footer
}


val lazyConfig: GridConfigurationScope.() -> Unit = {
    column(minmax(0.dp, 1.fr))
    row(GridTrackSize.MaxContent)
    row(minmax(0.dp, 1.fr))
    row(GridTrackSize.MaxContent)

    area(ScreenArea.Header, row = 1, column = 1)
    area(ScreenArea.Content, row = 2, column = 1)
    area(ScreenArea.Footer, row = 3, column = 1)
    gap(8.dp)
}

2. Coloca componentes estáticos en la cuadrícula

En tu elemento de componibilidad, pasa lazyConfig al contenedor Grid. Dentro de la lambda content, coloca componentes estáticos (Header y Footer) y ubícalos con Modifier.gridItem() con sus respectivos identificadores de área.

3. Incorpora LazyColumn en el área de contenido

En la celda de contenido, incorpora LazyColumn con Modifier.gridItem(ScreenArea.Content). Debido a que la pista de contenido se configuró con minmax(0.dp, 1.fr) en el paso 1, LazyColumn puede medir y reciclar elementos de forma segura en el desplazamiento sin consultar dimensiones intrínsecas no admitidas:

@Composable
fun GridWithLazyColumn(
    modifier: Modifier = Modifier,
    items: List<String> = emptyList(),
) {
    Grid(
        modifier = modifier.fillMaxSize(),
        config = lazyConfig
    ) {
        Text("Header", Modifier.gridItem(ScreenArea.Header).padding(16.dp))
        Text("Footer", Modifier.gridItem(ScreenArea.Footer).padding(16.dp))

        // LazyColumn placed in the content area for large datasets
        LazyColumn(
            modifier = Modifier
                .gridItem(ScreenArea.Content)
                .fillMaxSize(),
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            items(items) { item ->
                Text(item, Modifier.padding(16.dp))
            }
        }
    }
}

Resultados

El diseño de tu pantalla ahora utiliza la API de Grid para definir la estructura general de la página bidimensional, mientras que incorpora un LazyColumn en un segmento flexible con un tamaño de minmax para reciclar los elementos de la lista de manera eficiente y evitar excepciones de tiempo de ejecución.

Recursos adicionales