Cómo establecer las propiedades del contenedor

Puedes definir una configuración de contenedor de cuadrícula para crear diseños flexibles que se adapten a diferentes tamaños de pantalla y tipos de contenido. En esta página, se describe cómo hacer lo siguiente:

Define una cuadrícula

Una cuadrícula consta de columnas y filas. El elemento componible Grid tiene un parámetro config que acepta una expresión lambda para definir las columnas y filas dentro de GridConfigurationScope. En el siguiente ejemplo, se define una cuadrícula que tiene tres filas y dos columnas, cada una con un tamaño fijo especificado en Dp:

Grid(
    config = {
        repeat(2) {
            column(160.dp)
        }
        repeat(3) {
            row(90.dp)
        }
    }
) {
}

Coloca elementos en una cuadrícula

Grid toma los elementos de la IU en la lambda content y los coloca en las celdas de la cuadrícula. La cuadrícula dispone los elementos, independientemente de si definiste de forma explícita las filas y las columnas. De forma predeterminada, Grid intenta colocar un elemento de la IU en la celda de cuadrícula disponible de la fila. Si no puede, lo coloca en una celda de cuadrícula disponible de la siguiente fila. Si no hay celdas vacías, Grid crea una fila nueva.

En el siguiente ejemplo, la cuadrícula tiene seis celdas y coloca una tarjeta en cada una (figura 1). Cada celda de la cuadrícula es de 160dp × 90dp, lo que hace que el tamaño total de la cuadrícula sea de 320dp × 270dp.

Grid(
    config = {
        repeat(2) {
            column(160.dp)
        }
        repeat(3) {
            row(90.dp)
        }
    }
) {
    Card1()
    Card2()
    Card3()
    Card4()
    Card5()
    Card6()
}

Seis tarjetas se colocan en una cuadrícula que tiene tres filas y dos columnas.
Figura 1: Seis tarjetas se colocan en una cuadrícula que tiene tres filas y dos columnas.

Para cambiar este comportamiento predeterminado y que se complete por columna, establece la propiedad flow en GridFlow.Column.

Grid(
    config = {
        repeat(2) {
            column(160.dp)
        }
        repeat(3) {
            row(90.dp)
        }
        gap(8.dp)
        flow = GridFlow.Column // Grid tries to place items to fill the column
    },
) {
    Card1()
    Card2()
    Card3()
    Card4()
    Card5()
    Card6()
}

La función de flujo cambia la dirección para colocar los elementos.
Figura 2: GridFlow.Row (izquierda) y GridFlow.Column (derecha).

Administra el tamaño de las pistas

Las filas y las columnas se denominan colectivamente pista de cuadrícula. Puedes especificar el tamaño de una pista de cuadrícula con uno de los siguientes métodos:

  • Fijo (Dp): Asigna un tamaño específico (p.ej., column(180.dp)).
  • Porcentaje (Float): Asigna un porcentaje del espacio total disponible de 0.0f a 1.0f (p.ej., row(0.5f) para el 50%).
  • Flexible (Fr): Distribuye el espacio restante de forma proporcional después de que se calculan las pistas fijas y de porcentaje. Por ejemplo, si dos filas se establecen en 1.fr y 3.fr, esta última recibe el 75% de la altura restante.
  • Intrínseco: Ajusta el tamaño de la pista según el contenido que contiene. Para obtener más información, consulta Determina el tamaño de la pista de cuadrícula de forma intrínseca.

En el siguiente ejemplo, se usan las diferentes opciones de tamaño de pista para definir las alturas de las filas:

Grid(
    config = {
        column(1f)

        row(100.dp)
        row(0.2f)
        row(1.fr)
        row(GridTrackSize.Auto)
    },
    modifier = Modifier.height(480.dp)
) {
    PastelRedCard("Fixed(100.dp)")
        PastelGreenCard("Percentage(0.2f)")
    PastelBlueCard("Flex(1.fr)")
        PastelYellowCard("Auto")

}

Alturas de fila definidas con las cuatro opciones principales de tamaño de pista.
Figura 3. Alturas de fila definidas con las cuatro opciones principales de tamaño de pista en Grid.

Establece el tamaño mínimo para las pistas de cuadrícula flexibles

Cuando un contenedor de cuadrícula no tiene espacio restante, una pista flexible estándar puede reducirse a 0.dp. Para evitar esto y asegurarte de que el contenido no se aplaste, usa GridTrackSize.MinMax para aplicar un tamaño mínimo explícito y, al mismo tiempo, mantener la pista flexible.

En el siguiente ejemplo, se asigna al menos 100.dp a la primera fila:

Grid(
    config = {
        column(1f)
        // The first row has a minimum height of 100.dp and can expand to 
        // the half of the remaining space.
        row(GridTrackSize.MinMax(100.dp, 1.fr))
        // The second row takes the half of the remaining space.
        row(1.fr)
        // The third row has a fixed height of 200.dp.
        row(200.dp)
    },
    modifier = Modifier.size(360.dp) // Total grid height is 360.dp
) {
    PastelRedCard("MinMax(100.dp, 1.fr)")
        PastelGreenCard("Flex(1.fr)")
    PastelBlueCard("Fixed(200.dp)")
}

Alturas de fila definidas con las cuatro opciones principales de tamaño de pista.
Figura 4: La primera fila tiene al menos 100.dp de altura.

Establece el tamaño mínimo de la pista de cuadrícula para colocar listas diferidas

Las pistas flexibles estándar consultan automáticamente los tamaños intrínsecos de sus elementos secundarios para establecer un tamaño base. Sin embargo, Jetpack Compose prohíbe consultar los tamaños intrínsecos de SubcomposeLayout, que respalda componentes, como LazyColumn y LazyRow.

Colocar una lista diferida dentro de una pista flexible estándar provoca una falla de IllegalStateException. Para colocar listas diferidas de forma segura dentro de una pista de cuadrícula flexible, usa MinMax con un tamaño mínimo explícito (como 0.dp) para omitir el pase de medición intrínseco.

Grid(
    config = {
        column(1f)
        // The first row's height is determined by the height of the Text composable.
        row(GridTrackSize.Auto)
        // The second row occupies the remaining space, allowing the LazyColumn to scroll.
        row(GridTrackSize.MinMax(0.dp, 1.fr))

        gap(8.dp)
    },
    modifier = Modifier.size(width = 170.dp, height = 240.dp)
) {
    Text("LazyColumn in a Grid")
    // The LazyColumn is placed in the second row, filling the remaining space.
    LazyColumn(verticalArrangement = Arrangement.spacedBy(4.dp)) {
        items(100) { number ->
            PastelGreenCard("Card $number")
        }
    }
}

Alturas de fila definidas con las cuatro opciones principales de tamaño de pista.
Figura 5. LazyColumn en una celda de cuadrícula.

Determina el tamaño de la pista de cuadrícula de forma intrínseca

Puedes usar el tamaño intrínseco para un Grid cuando quieras que el diseño se adapte al contenido, en lugar de forzarlo a un contenedor fijo. El tamaño de la pista de cuadrícula se determina con los siguientes valores:

  • GridTrackSize.MaxContent: Usa el tamaño intrínseco máximo del contenido (p.ej., el ancho se determina por la longitud total del texto en un bloque de texto sin ajuste).
  • GridTrackSize.MinContent: Usa el tamaño intrínseco mínimo del contenido (p.ej., el ancho se determina por la palabra más larga en un bloque de texto).
  • GridTrackSize.Auto: Usa un tamaño flexible para una pista que se adapte según el espacio disponible. Se comporta como MaxContent de forma predeterminada, pero se reduce y ajusta su contenido para que quepa dentro del contenedor superior.

En el siguiente ejemplo, se colocan dos textos uno al lado del otro. El tamaño de la columna para el primer texto se determina según el ancho mínimo requerido para mostrar el texto, y el ancho de la segunda columna depende del ancho máximo requerido del texto.

Grid(
    config = {
        column(GridTrackSize.MinContent)
        column(GridTrackSize.MaxContent)
        row(1.0f)
    },
    modifier = Modifier.width(480.dp)
) {
    Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet.")
    Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet.")
}

Son los tamaños intrínsecos especificados en las columnas.
Figura 5. Son los tamaños intrínsecos especificados en las columnas.

Establece espacios entre filas y columnas

Una vez que hayas definido el tamaño de las pistas de la cuadrícula, puedes modificar el espacio entre ellas para definir mejor el espaciado. Puedes especificar el espacio entre columnas con la función columnGap y el espacio entre filas con rowGap. En el siguiente ejemplo, hay un espacio de 16dp entre cada fila y un espacio de 8dp entre cada columna (figura 5).

Grid(
    config = {
        repeat(2) {
            column(160.dp)
        }
        repeat(3) {
            row(90.dp)
        }
        rowGap(16.dp)
        columnGap(8.dp)
    }
) {
    Card1()
    Card2()
    Card3()
    Card4()
    Card5()
    Card6()
}

Espacios entre filas y columnas.
Figura 6. Espacios entre filas y columnas.

También puedes usar la función de conveniencia gap para definir espacios del mismo tamaño de columna y fila, y para definir tamaños de columna y espacio por separado con una sola función. El siguiente código agrega espacios de 8dp a la cuadrícula:

Grid(
    config = {
        repeat(2) {
            column(160.dp)
        }
        repeat(3) {
            row(90.dp)
        }
        gap(8.dp) // Equivalent to columnGap(8.dp) and rowGap(8.dp)
    }
) {
    Card1()
    Card2()
    Card3()
    Card4()
    Card5()
    Card6()
}

Define áreas de cuadrícula con áreas con nombre

Las áreas con nombre te permiten adjuntar nombres a grupos de celdas de cuadrícula, que se denominan áreas de cuadrícula. Puedes usar estos nombres en lugar de los índices de coordenadas cuando coloques elementos de la IU en la cuadrícula.

El uso de áreas con nombre tiene dos beneficios principales para la legibilidad del código:

  • Cuando se define el diseño de cuadrícula, el propósito y la ubicación del contenido esperado son claros.
  • Cuando se agrega el contenido, el propósito de este es claro.

Para organizar diseños complejos con claridad, puedes separar la estructura de la cuadrícula física de la ubicación de los elementos secundarios definiendo áreas de cuadrícula semánticas.

Dentro de la lambda config, usa la función area en GridConfigurationScope para registrar áreas con nombre en la cuadrícula. Luego, puedes asignar elementos componibles secundarios a estas áreas con el modificador gridItem con el identificador de área correspondiente. La función area asigna un identificador semántico (como un valor de clase enum o una clave de cadena) a un conjunto de coordenadas de cuadrícula físicas. Las líneas de cuadrícula y los índices se basan en 1 (es decir, la primera fila es 1 y la primera columna es 1).

Por ejemplo, defines una cuadrícula que tiene cuatro IDs de área:

/**
 * An enum representing the IDs for named areas within the grid.
 */
enum class GridAreaNames {
    Area1,
    Area2,
    Area3,
    Area4
}

Proporciona el nombre del área con el parámetro areaId junto con las coordenadas y los intervalos de las celdas del área. El modificador gridItem usa areaId como clave para asignar cada elemento secundario a su área de cuadrícula designada, como se muestra en el siguiente ejemplo:

Grid(
    config = {
        // Define a single column that takes all available width.
        repeat(2) { column(0.5f) }

        // Define four rows, each taking 25% of the total height.
        repeat(4) { row(0.25f) }

        // Define named grid areas by associating an areaId with specific row and column indices.
        // Row and column indices are 1-based.
        area(areaId = GridAreaNames.Area1, row = 1, column = 1, columnSpan = 2)
        area(areaId = GridAreaNames.Area2, row = 2, column = 1, rowSpan = 3)
        area(areaId = GridAreaNames.Area3, rows = 2..3, columns = 2..2)
        area(areaId = GridAreaNames.Area4, row = 4, column = 2)

        gap(4.dp)
    },
    modifier = Modifier.size(360.dp)
) {
    PastelRedCard(
        "Area 1",
        // Use Modifier.gridItem(areaId) to place this composable into the
        // grid area defined with the matching ID in the config block.
        modifier = Modifier.gridItem(areaId = GridAreaNames.Area1)
    )
    PastelGreenCard(
        "Area 2",
        modifier = Modifier.gridItem(areaId = GridAreaNames.Area2)
    )
    PastelBlueCard(
        "Area 3",
        modifier = Modifier.gridItem(areaId = GridAreaNames.Area3)
    )
    PastelYellowCard(
        "Area 4",
        modifier = Modifier.gridItem(areaId = GridAreaNames.Area4)
    )
}

Con las áreas con nombre, puedes reorganizar o ajustar la cuadrícula de diseño físico (por ejemplo, cambiar filas, columnas o tamaños de pistas) en la expresión lambda config sin necesidad de modificar el orden o los parámetros de los elementos componibles secundarios.