Definir propriedades do contêiner

É possível definir uma configuração de contêiner de grade para criar layouts flexíveis que respondem a diferentes tamanhos de tela e tipos de conteúdo. Esta página explica como fazer o seguinte:

Definir uma grade

Uma grade consiste em colunas e linhas. O elemento combinável Grid tem um parâmetro config que aceita uma lambda para definir as colunas e linhas em GridConfigurationScope. O exemplo a seguir define uma grade com três linhas e duas colunas, cada uma com um tamanho fixo especificado em Dp:

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

Colocar itens em uma grade

Grid usa os elementos de IU na lambda content e os coloca em células de grade. A grade organiza os itens, independentemente de você ter definido explicitamente as linhas e colunas. Por padrão, Grid tenta colocar um elemento da interface na célula de grade disponível na linha. Se não for possível, ele será colocado em uma célula de grade disponível na próxima linha. Se não houver células vazias, Grid cria uma nova linha.

No exemplo a seguir, a grade tem seis células e coloca um card em cada uma delas (Figura 1). Cada célula de grade tem 160dp x 90dp, o que torna o tamanho total da grade 320dp x 270dp.

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

Seis cards são colocados em uma grade com três linhas e duas colunas.
Figura 1. Seis cards são colocados em uma grade com três linhas e duas colunas.

Para mudar esse comportamento padrão para preenchimento por coluna, defina a propriedade flow como 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()
}

A função de fluxo muda a direção para colocar itens.
Figura 2. GridFlow.Row (à esquerda) e GridFlow.Column (à direita).

Gerenciar o dimensionamento de faixas

Linhas e colunas são chamadas coletivamente de faixa de grade. É possível especificar o tamanho de uma faixa de grade usando um dos seguintes métodos:

  • Fixo (Dp): aloca um tamanho específico (por exemplo, column(180.dp)).
  • Porcentagem (Float): aloca uma porcentagem do espaço disponível total de 0.0f a 1.0f (por exemplo, row(0.5f) para 50%).
  • Flexível (Fr): distribui o espaço restante proporcionalmente após o cálculo das faixas fixas e de porcentagem. Por exemplo, se duas linhas forem definidas como 1.fr e 3.fr, a última receberá 75% da altura restante.
  • Intrínseco: dimensiona a faixa com base no conteúdo dela. Para mais informações, consulte Determinar o tamanho da faixa de grade intrinsecamente.

O exemplo a seguir usa as diferentes opções de dimensionamento de faixas para definir as alturas das linhas:

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 linha definidas usando as quatro opções principais de dimensionamento de faixa.
Figura 3. Alturas de linha definidas usando as quatro opções principais de dimensionamento de faixas em Grid.

Definir o tamanho mínimo para faixas de grade flexíveis

Quando um contêiner de grade não tem espaço restante, uma faixa flexível padrão pode ser reduzida para 0.dp. Para evitar isso e garantir que o conteúdo não seja compactado, use GridTrackSize.MinMax para aplicar um tamanho mínimo explícito, mantendo a faixa flexível.

O exemplo a seguir aloca pelo menos 100.dp para a primeira linha:

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 linha definidas usando as quatro opções principais de dimensionamento de faixa.
Figura 4. A primeira linha tem pelo menos 100.dp de altura.

Definir o tamanho mínimo da faixa de grade para colocar listas lentas

As faixas flexíveis padrão consultam automaticamente os tamanhos intrínsecos dos filhos para estabelecer um tamanho base. No entanto, o Jetpack Compose proíbe a consulta dos tamanhos intrínsecos de SubcomposeLayout, que oferece suporte a componentes, como LazyColumn e LazyRow.

A colocação de uma lista lenta em uma faixa flexível padrão causa uma falha IllegalStateException. Para colocar listas lentas com segurança em uma faixa de grade flexível, use MinMax com um tamanho mínimo explícito (como 0.dp) para ignorar a passagem de medição intrínseca.

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("Lazy column 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 linha definidas usando as quatro opções principais de dimensionamento de faixa.
Figura 5. LazyColumn em uma célula de grade.

Determinar o tamanho da faixa de grade intrinsecamente

É possível usar o dimensionamento intrínseco para um Grid quando você quer que o layout se adapte ao conteúdo, em vez de forçá-lo a um contêiner fixo. O tamanho da faixa de grade é determinado pelos seguintes valores:

  • GridTrackSize.MaxContent: usa o tamanho intrínseco máximo do conteúdo (por exemplo, a largura é determinada pelo comprimento total do texto em um bloco de texto sem quebra de linha).
  • GridTrackSize.MinContent: usa o tamanho intrínseco mínimo do conteúdo (por exemplo, a largura é determinada pela palavra única mais longa em um bloco de texto).
  • GridTrackSize.Auto: usa um tamanho flexível para uma faixa que se adapta com base no espaço disponível. Ele se comporta como MaxContent por padrão, mas encolhe e envolve o conteúdo para caber no contêiner pai.

O exemplo a seguir coloca dois textos lado a lado. O tamanho da coluna do primeiro texto é determinado pela largura mínima necessária para exibir o texto, e a largura da segunda coluna depende da largura máxima necessária do 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.")
}

Tamanhos intrínsecos especificados nas colunas.
Figura 5. Tamanhos intrínsecos especificados nas colunas.

Definir lacunas entre linhas e colunas

Depois que as faixas de grade forem dimensionadas, você poderá modificar a lacuna da grade para refinar o espaçamento entre as faixas. É possível especificar a lacuna da coluna com a columnGap função, e a lacuna da linha com rowGap. No exemplo a seguir, há uma lacuna de 16dp entre cada linha e uma lacuna de 8dp entre cada coluna (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()
}

Lacunas entre linhas e colunas.
Figura 6. Lacunas entre linhas e colunas.

Também é possível usar a função de conveniência gap para definir lacunas do mesmo tamanho de coluna e linha, e para definir tamanhos de coluna e lacuna separadamente usando uma única função. O código a seguir adiciona lacunas de 8dp à grade:

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()
}