É 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: configure a estrutura básica de linhas e colunas.
- Colocar itens em uma grade: entenda como os itens são colocados nas células da grade e como mudar a direção do fluxo.
- Gerenciar o dimensionamento de faixas: use o dimensionamento fixo, percentual, flexível e intrínseco para definir os tamanhos das faixas.
- Definir lacunas: gerencie as "calhas" entre linhas e colunas.
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 da interface
na lambda content e os coloca em células de grade.
A grade organiza os itens, mesmo que
você não tenha definido explicitamente as linhas e colunas.
Por padrão,
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, o Grid vai criar uma nova linha.
No exemplo a seguir, a grade tem seis células
e coloca um card em cada uma (Figura 1).
Cada célula da grade tem 160dp x 90dp,
totalizando 320dp x 270dp.
Grid( config = { repeat(2) { column(160.dp) } repeat(3) { row(90.dp) } } ) { Card1() Card2() Card3() Card4() Card5() Card6() }
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() }
GridFlow.Row (à esquerda) e GridFlow.Column (à direita).
Gerenciar o dimensionamento de faixas
As 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 total disponível de0.0fa1.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 percentuais. Por exemplo, se duas linhas forem definidas como1.fre3.fr, a última vai 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 de forma intrínseca.
O exemplo a seguir usa as diferentes opções de dimensionamento de faixa 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") }
Grid.
Definir o tamanho mínimo para faixas de grade flexíveis
Quando um contêiner de grade não tem mais espaço,
uma faixa flexível padrão pode ser reduzida para 0.dp.
Para evitar isso e garantir que o conteúdo não seja esmagado,
use GridTrackSize.MinMax
para aplicar um tamanho mínimo explícito e manter a flexibilidade da faixa.
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)") }
100.dp de altura.
Definir o tamanho mínimo da faixa de grade para posicionar 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.
Colocar uma lista lenta dentro de uma faixa flexível padrão causa
uma falha de 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 transmissão 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("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") } } }
LazyColumn em uma célula da grade.
Determinar o tamanho da faixa de grade de forma intrínseca
Você pode usar o dimensionamento intrínseco para um Grid
quando quiser que o layout se adapte ao conteúdo,
em vez de forçá-lo em um contêiner fixo.
O tamanho da faixa da grade é determinado com os seguintes valores:
GridTrackSize.MaxContent: use 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 mais longa em um bloco de texto).GridTrackSize.Auto: use um tamanho flexível para uma faixa que se adapta com base no espaço disponível. Ele se comporta comoMaxContentpor padrão, mas reduz e une o conteúdo para que ele caiba 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 mostrar 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.") }
Definir lacunas entre linhas e colunas
Depois de dimensionar as faixas da grade,
é possível modificar o espaçamento da grade para ajustar o espaçamento entre as faixas.
É possível especificar o espaçamento entre colunas com a função columnGap
e o espaçamento entre linhas com rowGap. No exemplo a seguir,
há um intervalo de 16dp entre cada linha
e um intervalo 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() }
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() }
Definir áreas de grade com áreas nomeadas
As áreas nomeadas permitem que você atribua nomes a grupos de células de grade, que são chamados de áreas de grade. É possível usar esses nomes em vez de índices de coordenadas ao colocar elementos da interface na grade.
O uso de áreas nomeadas tem dois benefícios principais para a legibilidade do código:
- Ao definir o layout de grade, o propósito e o posicionamento do conteúdo esperado ficam claros.
- Ao adicionar o conteúdo, o propósito dele é claro.
Para organizar layouts complexos de forma clara, é possível separar a estrutura física da grade do posicionamento dos filhos definindo áreas de grade semânticas.
Dentro da lambda config, use a função area em
GridConfigurationScope para registrar áreas nomeadas na grade.
Em seguida, você pode atribuir elementos de composição filhos a essas áreas
usando o modificador gridItem
com o identificador de área correspondente. A função area mapeia
um identificador semântico (como um valor de classe enum ou uma chave de string) para
um conjunto de coordenadas de grade física. As linhas de grade e os índices são baseados em 1
(ou seja, a primeira linha é 1 e a primeira coluna é 1).
Por exemplo, você define uma grade com quatro IDs de área:
/** * An enum representing the IDs for named areas within the grid. */ enum class GridAreaNames { Area1, Area2, Area3, Area4 }
Informe o nome da área usando o parâmetro areaId com as coordenadas e as extensões de célula da área.
O modificador gridItem usa o areaId como uma chave
para atribuir cada item filho à área de grade designada,
conforme mostrado no exemplo abaixo:
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) ) }
Ao usar áreas nomeadas, é possível reorganizar ou ajustar o layout de grade físico (por
exemplo, mudando linhas, colunas ou tamanhos de faixas) na lambda config
sem precisar modificar a ordem ou os parâmetros dos elementos combináveis filhos.