ConstraintLayout no Compose (original) (raw)
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 elementosRow, Column, Box aninhados e outros elementos de layout personalizados.
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. Por isso, o ConstraintLayout não é tão benéfico.
Comece a curtir o canal ConstraintLayout
Para usar o ConstraintLayout no Compose, é necessário adicionar essa dependência aobuild.gradle, além da configuração do Compose:
implementation "androidx.constraintlayout:constraintlayout-compose:$constraintlayout_compose_version"
No Compose, o ConstraintLayout funciona da seguinte maneira usando umaDSL:
- Crie referências para cada elemento combinável no
ConstraintLayoutusandocreateRefs() ou createRefFor(). - As restrições são fornecidas usando 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óprioConstraintLayoutde 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 de16.dp e um Text na parte inferior de Button, também com uma margem de16.dp.
Figura 1. Um elemento combinável Button e um Text restritos um ao outro em umConstraintLayout.
API dissociada
No exemplo de ConstraintLayout, as restrições são especificadas inline, com um modificador no elemento combinável 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 para
ConstraintLayout. - Atribua referências criadas no
ConstraintSetaos elementos combináveis usando o modificador layoutId.
@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 umConstraintSet 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 determinadadp 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 eend.
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 referenciam vários elementos combináveis para criar 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 oucreateHorizontalChain:
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.