O ConstraintLayout
é um layout que permite posicionar elementos combináveis em relação
a outros elementos na tela. Essa é uma alternativa ao uso de vários elementos
Row
, Column
, Box
aninhados e outros elementos de layout personalizados. O ConstraintLayout
é útil para implementar layouts maiores com requisitos de alinhamento
mais complicados.
Use ConstraintLayout
nos seguintes cenários:
- Para evitar o aninhamento de vários
Column
s eRow
s quando for posicionar elementos na tela para melhorar a legibilidade do código. - Para posicionar elementos de composição em relação a outros ou para posicionar elementos com base em diretrizes, barreiras ou cadeias.
No sistema de visualização, ConstraintLayout
era a maneira recomendada de criar
layouts grandes e complexos, já que uma hierarquia de visualização plana era melhor para o desempenho
do que as visualizações aninhadas. No entanto, isso não é um problema no Compose, que consegue processar
hierarquias de layout profundas com eficiência.
Comece a usar o ConstraintLayout
Para usar o ConstraintLayout
no Compose, é necessário adicionar essa dependência ao
build.gradle
, além da
configuração do Compose:
implementation "androidx.constraintlayout:constraintlayout-compose:1.0.1"
No Compose, o ConstraintLayout
funciona da seguinte maneira usando uma
DSL:
- Crie referências para cada elemento combinável no
ConstraintLayout
usandocreateRefs()
oucreateRefFor()
. - As restrições são fornecidas com o modificador
constrainAs()
, que usa a referência como um parâmetro e permite especificar as restrições no lambda do corpo. - As restrições são especificadas usando
linkTo()
ou outros métodos úteis. parent
é uma referência atual que pode ser usada para especificar restrições no próprioConstraintLayout
de composição.
Veja o exemplo de um elemento de composição usando ConstraintLayout
:
@Composable fun ConstraintLayoutContent() { ConstraintLayout { // Create references for the composables to constrain val (button, text) = createRefs() Button( onClick = { /* Do something */ }, // Assign reference "button" to the Button composable // and constrain it to the top of the ConstraintLayout modifier = Modifier.constrainAs(button) { top.linkTo(parent.top, margin = 16.dp) } ) { Text("Button") } // Assign reference "text" to the Text composable // and constrain it to the bottom of the Button composable Text( "Text", Modifier.constrainAs(text) { top.linkTo(button.bottom, margin = 16.dp) } ) } }
Esse código restringe o topo do Button
ao pai com uma margem de
16.dp
e um Text
na parte inferior de Button
, também com uma margem de
16.dp
.
API dissociada
No exemplo do ConstraintLayout
,
as restrições são especificadas inline, com um modificador na função de composição
a que elas são aplicadas. No entanto, há situações em que é preferível dissociar as restrições dos layouts aos
que elas se aplicam. Por exemplo, talvez você queira
mudar as restrições com base na configuração da tela ou colocar uma animação entre dois
conjuntos de restrições.
Para casos como esses, é possível usar ConstraintLayout
de uma maneira diferente:
- Transmita um
ConstraintSet
como um parâmetro paraConstraintLayout
. - Atribua referências criadas no
ConstraintSet
aos elementos combináveis usando o modificadorlayoutId
.
@Composable fun DecoupledConstraintLayout() { BoxWithConstraints { val constraints = if (minWidth < 600.dp) { decoupledConstraints(margin = 16.dp) // Portrait constraints } else { decoupledConstraints(margin = 32.dp) // Landscape constraints } ConstraintLayout(constraints) { Button( onClick = { /* Do something */ }, modifier = Modifier.layoutId("button") ) { Text("Button") } Text("Text", Modifier.layoutId("text")) } } } private fun decoupledConstraints(margin: Dp): ConstraintSet { return ConstraintSet { val button = createRefFor("button") val text = createRefFor("text") constrain(button) { top.linkTo(parent.top, margin = margin) } constrain(text) { top.linkTo(button.bottom, margin) } } }
Assim, quando precisar mudar as restrições, basta transmitir um
ConstraintSet
diferente.
Conceitos de ConstraintLayout
O ConstraintLayout
contém conceitos, como diretrizes, barreiras e cadeias,
que podem ajudar a posicionar elementos dentro do elemento combinável.
Diretrizes
Diretrizes são pequenos auxiliares visuais para criar layouts. Os elementos de composição podem
ser restritos a uma diretriz. Elas são úteis para posicionar elementos em uma determinada
dp
ou percentage
dentro do elemento combinável pai.
Há dois tipos de diretrizes: vertical e horizontal. Os dois
horizontais são top
e bottom
, e os dois verticais são start
e
end
.
ConstraintLayout { // Create guideline from the start of the parent at 10% the width of the Composable val startGuideline = createGuidelineFromStart(0.1f) // Create guideline from the end of the parent at 10% the width of the Composable val endGuideline = createGuidelineFromEnd(0.1f) // Create guideline from 16 dp from the top of the parent val topGuideline = createGuidelineFromTop(16.dp) // Create guideline from 16 dp from the bottom of the parent val bottomGuideline = createGuidelineFromBottom(16.dp) }
Para criar uma diretriz, use o createGuidelineFrom*
com o tipo de diretriz
necessário. Isso cria uma referência que pode ser usada no
bloco Modifier.constrainAs()
.
Barreiras
As barreiras são vários elementos combináveis quem criam uma diretriz virtual com base no widget mais extremo do lado especificado.
Para criar uma, use createTopBarrier()
(ou: createBottomBarrier()
,
createEndBarrier()
, createStartBarrier()
) e forneça as referências que
precisam compor a barreira.
ConstraintLayout { val constraintSet = ConstraintSet { val button = createRefFor("button") val text = createRefFor("text") val topBarrier = createTopBarrier(button, text) } }
A barreira pode ser usada em um bloco Modifier.constrainAs()
.
Cadeias
As cadeias fornecem comportamentos semelhantes a grupos em um único eixo (horizontal ou vertical). O outro eixo pode ser restrito de maneira independente.
Para criar uma cadeia, use createVerticalChain
ou createHorizontalChain
:
ConstraintLayout { val constraintSet = ConstraintSet { val button = createRefFor("button") val text = createRefFor("text") val verticalChain = createVerticalChain(button, text, chainStyle = ChainStyle.Spread) val horizontalChain = createHorizontalChain(button, text) } }
A cadeia pode ser usada no bloco Modifier.constrainAs()
.
Uma cadeia pode ser configurada com diferentes ChainStyles
, que decidem como lidar
com o espaço ao redor de um elemento combinável, como:
ChainStyle.Spread
: o espaço é distribuído uniformemente entre todos os elementos de composição, incluindo o espaço livre antes do primeiro elemento e após o último.ChainStyle.SpreadInside
: o espaço é distribuído uniformemente entre todos os elementos de composição, sem que haja espaço livre antes do primeiro elemento ou após o último.ChainStyle.Packed
: o espaço é distribuído antes do primeiro e depois do último elemento combinável. Esses elementos são compactados sem espaço entre si.
Saiba mais
Saiba mais sobre o ConstraintLayout
no Compose e confira as APIs em ação nos
exemplos do Compose que usam o ConstraintLayout
(em inglês).
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- Foco no Compose
- Kotlin para Jetpack Compose
- Conceitos básicos de layout do Compose