FlowRow
e FlowColumn
são elementos combináveis semelhantes a Row
e Column
, mas diferem porque os itens
fluem para a próxima linha quando o contêiner fica sem espaço. Isso cria
várias linhas ou colunas. O número de itens em uma linha também pode ser controlado
definindo maxItemsInEachRow
ou maxItemsInEachColumn
. Muitas vezes, é possível usar
FlowRow
e FlowColumn
para criar layouts responsivos. O conteúdo não será cortado
se os itens forem muito grandes para uma dimensão. Usar uma combinação de
maxItemsInEach*
com Modifier.weight(weight)
pode ajudar a criar layouts que
preencham/expandam a largura de uma linha ou coluna quando necessário.
O exemplo típico é para uma IU de filtro ou ícone:
Uso básico
Para usar FlowRow
ou FlowColumn
, crie esses elementos combináveis e coloque os itens
dentro deles que precisam seguir o fluxo padrão:
@Composable private fun FlowRowSimpleUsageExample() { FlowRow(modifier = Modifier.padding(8.dp)) { ChipItem("Price: High to Low") ChipItem("Avg rating: 4+") ChipItem("Free breakfast") ChipItem("Free cancellation") ChipItem("£50 pn") } }
Esse snippet resulta na interface mostrada acima, com os itens fluindo automaticamente para a próxima linha quando não há mais espaço na primeira.
Recursos do layout de fluxo
Os layouts de fluxo têm os seguintes recursos e propriedades que podem ser usados para criar layouts diferentes no app.
Posição do eixo principal: horizontal ou vertical
O eixo principal é aquele em que os itens são dispostos. Por exemplo, em
FlowRow
, os itens são organizados horizontalmente. O parâmetro horizontalArrangement
em FlowRow
controla a forma como o espaço livre é distribuído entre os itens.
A tabela abaixo mostra exemplos de como definir horizontalArrangement
em itens
para FlowRow
:
Organização horizontal definida em |
Resultado |
|
|
Para FlowColumn
, opções semelhantes estão disponíveis com verticalArrangement
, com
o padrão Arrangement.Top
.
Disposição entre eixos
O eixo cruzado é o eixo na direção oposta ao eixo principal. Por
exemplo, em FlowRow
, esse é o eixo vertical. Se quiser mudar a forma como o conteúdo geral dentro do contêiner é organizado no eixo cruzado, use verticalArrangement
para FlowRow
e horizontalArrangement
para FlowColumn
.
Para FlowRow
, a tabela a seguir mostra exemplos de como definir diferentes
verticalArrangement
nos itens:
Organização vertical definida em |
Resultado |
|
|
Para FlowColumn
, opções semelhantes estão disponíveis com horizontalArrangement
.
A organização padrão de eixo cruzado é Arrangement.Start
.
Alinhamento de itens individuais
É possível posicionar itens individuais na linha com diferentes
alinhamentos. Isso é diferente de verticalArrangement
e
horizontalArrangement
, porque alinha os itens na linha atual. Você pode
aplicar isso com Modifier.align()
.
Por exemplo, quando os itens em um FlowRow
têm alturas diferentes, a linha usa a
altura do item maior e aplica Modifier.align(alignmentOption)
aos
itens:
Alinhamento vertical definido em |
Resultado |
|
|
Para FlowColumn
, opções semelhantes estão disponíveis. O alinhamento padrão é
Alignment.Start
.
Itens máximos na linha ou coluna
Os parâmetros maxItemsInEachRow
ou maxItemsInEachColumn
definem o número máximo
de itens no eixo principal permitidos em uma linha antes de passar para a próxima. O
padrão é Int.MAX_INT
, que permite o máximo de itens possível, desde que
os tamanhos deles permitam que eles caibam na linha.
Por exemplo, definir um maxItemsInEachRow
força o layout inicial a ter apenas
três itens:
Nenhum valor máximo definido |
|
Itens de fluxo com carregamento lento
ContextualFlowRow
e ContextualFlowColumn
são uma versão especializada
de FlowRow
e FlowColumn
que permitem carregar o conteúdo
da linha ou coluna do fluxo de maneira lenta. Eles também fornecem informações sobre a posição dos itens
(índice, número de linha e tamanho disponível), como se o item está na primeira
linha. Isso é útil para grandes conjuntos de dados e se você precisar de informações contextuais
sobre um item.
O parâmetro maxLines
limita o número de linhas exibidas, e o parâmetro overflow
especifica o que será mostrado quando um overflow de itens for
atingido, permitindo que você especifique um expandIndicator
ou
collapseIndicator
personalizado.
Por exemplo, para mostrar um botão "+ (número de itens restantes)" ou "Mostrar menos":
val totalCount = 40 var maxLines by remember { mutableStateOf(2) } val moreOrCollapseIndicator = @Composable { scope: ContextualFlowRowOverflowScope -> val remainingItems = totalCount - scope.shownItemCount ChipItem(if (remainingItems == 0) "Less" else "+$remainingItems", onClick = { if (remainingItems == 0) { maxLines = 2 } else { maxLines += 5 } }) } ContextualFlowRow( modifier = Modifier .safeDrawingPadding() .fillMaxWidth(1f) .padding(16.dp) .wrapContentHeight(align = Alignment.Top) .verticalScroll(rememberScrollState()), verticalArrangement = Arrangement.spacedBy(4.dp), horizontalArrangement = Arrangement.spacedBy(8.dp), maxLines = maxLines, overflow = ContextualFlowRowOverflow.expandOrCollapseIndicator( minRowsToShowCollapse = 4, expandIndicator = moreOrCollapseIndicator, collapseIndicator = moreOrCollapseIndicator ), itemCount = totalCount ) { index -> ChipItem("Item $index") }
Pesos do item
O peso aumenta um item com base no fator dele e no espaço disponível na linha em que ele
foi colocado. É importante ressaltar que há uma diferença entre FlowRow
e Row
com a forma como os pesos são usados para calcular a largura de um item. Para Rows
, o peso
é baseado em todos os itens em Row
. Com FlowRow
, o peso é baseado nos
itens na linha em que um item é colocado, e não em todos os itens no
contêiner FlowRow
.
Por exemplo, se você tiver quatro itens que caem em uma linha, cada um com pesos
diferentes de 1f, 2f, 1f
e 3f
, o peso total será 7f
. O espaço restante
em uma linha ou coluna será dividido por 7f
. Em seguida, a largura de cada item será
calculada usando: weight * (remainingSpace / totalWeight)
.
É possível usar uma combinação de Modifier.weight
e itens máximos com FlowRow
ou
FlowColumn
para criar um layout semelhante a uma grade. Essa abordagem é útil para criar
layouts responsivos que se ajustam ao tamanho do dispositivo.
Confira alguns exemplos do que você pode fazer usando pesos. Um exemplo é uma grade em que os itens têm o mesmo tamanho, conforme mostrado abaixo:
Para criar uma grade de tamanhos iguais de itens, faça o seguinte:
val rows = 3 val columns = 3 FlowRow( modifier = Modifier.padding(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), maxItemsInEachRow = rows ) { val itemModifier = Modifier .padding(4.dp) .height(80.dp) .weight(1f) .clip(RoundedCornerShape(8.dp)) .background(MaterialColors.Blue200) repeat(rows * columns) { Spacer(modifier = itemModifier) } }
Se você adicionar outro item e repeti-lo 10 vezes em vez de 9, o
último item ocupará toda a última coluna, já que o peso total da linha
é 1f
:
É possível combinar pesos com outros Modifiers
, como
Modifier.width(exactDpAmount), Modifier.aspectRatio(aspectRatio)
ou
Modifier.fillMaxWidth(fraction)
. Todos esses modificadores trabalham em conjunto para
permitir o dimensionamento responsivo de itens em um FlowRow
(ou FlowColumn
).
Você também pode criar uma grade alternada de tamanhos de itens diferentes, em que dois itens ocupam metade da largura cada e um item ocupa a largura total da próxima coluna:
Para fazer isso, use o seguinte código:
FlowRow( modifier = Modifier.padding(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), maxItemsInEachRow = 2 ) { val itemModifier = Modifier .padding(4.dp) .height(80.dp) .clip(RoundedCornerShape(8.dp)) .background(Color.Blue) repeat(6) { item -> // if the item is the third item, don't use weight modifier, but rather fillMaxWidth if ((item + 1) % 3 == 0) { Spacer(modifier = itemModifier.fillMaxWidth()) } else { Spacer(modifier = itemModifier.weight(0.5f)) } } }
Dimensionamento fracionário
Usando Modifier.fillMaxWidth(fraction)
, é possível especificar o tamanho do
contêiner que um item precisa ocupar. Isso é diferente de como
Modifier.fillMaxWidth(fraction)
funciona quando aplicado a Row
ou Column
, porque
os itens Row/Column
ocupam uma porcentagem da largura restante, em vez de
todo o contêiner.
Por exemplo, o código a seguir produz resultados diferentes ao usar FlowRow
em vez de Row
:
FlowRow( modifier = Modifier.padding(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), maxItemsInEachRow = 3 ) { val itemModifier = Modifier .clip(RoundedCornerShape(8.dp)) Box( modifier = itemModifier .height(200.dp) .width(60.dp) .background(Color.Red) ) Box( modifier = itemModifier .height(200.dp) .fillMaxWidth(0.7f) .background(Color.Blue) ) Box( modifier = itemModifier .height(200.dp) .weight(1f) .background(Color.Magenta) ) }
|
|
|
fillMaxColumnWidth()
e fillMaxRowHeight()
Aplicar Modifier.fillMaxColumnWidth()
ou
Modifier.fillMaxRowHeight()
a um item dentro de um FlowColumn
ou FlowRow
garante que os itens na mesma coluna ou linha ocupem a mesma largura ou altura que
o item maior na coluna/linha.
Por exemplo, este exemplo usa FlowColumn
para mostrar a lista de sobremesas
do Android. É possível notar a diferença na largura de cada item quando
Modifier.fillMaxColumnWidth()
é aplicado a eles em comparação com quando ele não é e
os itens são agrupados.
FlowColumn( Modifier .padding(20.dp) .fillMaxHeight() .fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp), maxItemsInEachColumn = 5, ) { repeat(listDesserts.size) { Box( Modifier .fillMaxColumnWidth() .border(1.dp, Color.DarkGray, RoundedCornerShape(8.dp)) .padding(8.dp) ) { Text( text = listDesserts[it], fontSize = 18.sp, modifier = Modifier.padding(3.dp) ) } } }
|
|
Nenhuma mudança de largura definida (itens de quebra de linha) |
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- Conceitos básicos de layout do Compose
- ConstraintLayout no Compose
- Ações do editor {:#editor-actions}