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 grandes demais para uma dimensão, e o uso de 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 interface de chip ou filtragem:
Uso básico
Para usar FlowRow
ou FlowColumn
, crie esses elementos combináveis e coloque os itens
dentro dele, 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 recursos e propriedades abaixo que podem ser usados para criar diferentes layouts no seu app.
Organização do eixo principal: organização 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 de Arrangement.Top
.
Disposição entre eixos
O eixo transversal é o eixo na direção oposta do eixo principal. Por
exemplo, em FlowRow
, esse é o eixo vertical. Se quiser mudar 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 abaixo mostra exemplos de como definir
verticalArrangement
diferentes 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
, já que alinha os itens na linha atual. É possível
aplicar isso com Modifier.align()
.
Por exemplo, quando os itens em uma FlowRow
têm alturas diferentes, a linha usa a
altura do maior item e aplica Modifier.align(alignmentOption)
a eles:
Alinhamento vertical definido em |
Resultado |
|
|
Para FlowColumn
, opções semelhantes estão disponíveis. O alinhamento padrão é
Alignment.Start
.
Máximo de itens na linha ou coluna
Os parâmetros maxItemsInEachRow
ou maxItemsInEachColumn
definem o número máximo
de itens no eixo principal a serem permitidos em uma linha antes de mudar para a próxima. O
padrão é Int.MAX_INT
, que permite o máximo de itens possível, desde que
o tamanho permita que eles se encaixem na linha.
Por exemplo, definir uma maxItemsInEachRow
força o layout inicial a ter apenas
três itens:
Nenhum máximo definido |
|
Itens de fluxo com carregamento lento
ContextualFlowRow
e ContextualFlowColumn
são uma versão especializada
de FlowRow
e FlowColumn
que permitem o carregamento lento do conteúdo
da linha ou coluna do fluxo. Eles também fornecem informações sobre a posição dos itens
(índice, número da linha e tamanho disponível), por exemplo, 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 precisa ser exibido quando um estouro de itens é 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, não em todos os itens no
contêiner FlowRow
.
Por exemplo, se você tiver quatro itens que se enquadram 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)
.
Você pode 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.
Há alguns exemplos diferentes do que é possível conseguir 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) } }
É importante ressaltar que, se você adicionar outro item e repeti-lo 10 vezes em vez de nove, o
último item ocupa toda a última coluna, já que o peso total da linha inteira
é 1f
:
É possível combinar ponderações com outros Modifiers
, como
Modifier.width(exactDpAmount), Modifier.aspectRatio(aspectRatio)
ou
Modifier.fillMaxWidth(fraction)
. Todos esses modificadores funcionam em conjunto para
permitir o dimensionamento responsivo de itens em uma FlowRow
(ou FlowColumn
).
Você também pode criar uma grade alternada de tamanhos de item diferentes, em que dois itens ocupam metade da largura cada, e um item ocupa toda a largura da próxima coluna:
Você pode fazer isso com 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)) } } }
Tamanho 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
e 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 FlowColumn
ou FlowRow
garante que os itens na mesma coluna ou linha ocupem a mesma largura ou altura que
o maior item na coluna/linha.
Por exemplo, este exemplo usa FlowColumn
para mostrar a lista de sobremesas
do Android. Você pode conferir a diferença nas larguras de cada item quando
Modifier.fillMaxColumnWidth()
é aplicado aos itens em relação a quando não são e
os itens são unidos.
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 alteração de largura definida (agrupamento de itens) |
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}