ConstraintLayout no Compose

ConstraintLayout pode ajudar a posicionar as funções que podem ser compostas em relação a outras na tela. Essa é uma alternativa ao uso de várias Row, Column e Box aninhadas e de elementos de layouts personalizados. ConstraintLayout é útil para implementar layouts maiores com requisitos de alinhamento mais complicados.

Para usar ConstraintLayout no Compose, é necessário adicionar esta dependência ao build.gradle:

implementation "androidx.constraintlayout:constraintlayout-compose:1.0.0-beta02"

No Compose, ConstraintLayout funciona com uma DSL (link em inglês):

  • As referências são criadas usando createRefs() ou createRefFor(), e cada função que pode ser composta em ConstraintLayout precisa ter uma referência associada a ela.
  • 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 já existente que pode ser usada para especificar restrições no próprio ConstraintLayout que pode ser composto.

Veja um exemplo de elemento que pode ser composto usando um 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.

Mostra um botão e um elemento de texto organizados em um ConstraintLayout

Para ver mais exemplos de como trabalhar com ConstraintLayout, consulte o codelab de layouts.

API dissociada

No exemplo do ConstraintLayout, as restrições são especificadas in-line, com um modificador na função que pode ser composta 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:

  1. Transmita um ConstraintSet como um parâmetro para ConstraintLayout.
  2. Atribua referências criadas no ConstraintSet aos elementos que podem ser compostos 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 um ConstraintSet diferente.

Saiba mais

Saiba mais sobre o ConstraintLayout no Compose na seção Layout restrito do codelab de Layouts no Jetpack Compose e veja as APIs em ação nos exemplos do Compose que usam ConstraintLayout (link em inglês).