ConstraintLayout en Compose

ConstraintLayout puede ayudar a posicionar elementos componibles en relación con otros en la pantalla y es una alternativa al uso de varios Row, Column, Box anidados y diseños personalizados. ConstraintLayout resulta útil cuando se implementan diseños más grandes con requisitos de alineación más complejos.

Para usar ConstraintLayout en Compose, debes agregar esta dependencia en tu build.gradle:

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

En Compose, ConstraintLayout funciona con una DSL:

  • Las referencias se crean con createRefs() o createRefFor(), y cada elemento componible en ConstraintLayout debe tener una referencia asociada.
  • Las restricciones se proporcionan mediante el modificador constrainAs(), que toma la referencia como parámetro y te permite especificar sus restricciones en la expresión lambda del cuerpo.
  • Las restricciones se especifican mediante linkTo() o algún otro método útil.
  • parent es una referencia existente que se puede usar para especificar restricciones hacia el mismo elemento ConstraintLayout.

En este ejemplo vemos uno de esos elementos que usa un 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)
        })
    }
}

Este código restringe la parte superior del Button al elemento superior, con un margen de 16.dp, y un Text a la parte inferior del Button, también con un margen de 16.dp.

Muestra un botón y un elemento de texto organizados en un ConstraintLayout

A fin de obtener más ejemplos para trabajar con ConstraintLayout, prueba el codelab de diseños.

API desacoplada

En el ejemplo de ConstraintLayout, las restricciones se especifican de forma intercalada, con un modificador en el elemento que admite composición al que se aplican. Sin embargo, hay situaciones en las que es preferible desacoplar las restricciones de los diseños a los que se aplican. Por ejemplo, quizás querrías cambiar las restricciones en función de la configuración de la pantalla o agregar una animación entre dos conjuntos de restricciones.

En casos como esos, puedes usar ConstraintLayout de otro modo:

  1. Pasa un ConstraintSet como parámetro a ConstraintLayout.
  2. Asigna referencias creadas en el ConstraintSet a los elementos que admiten composición con el 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)
        }
    }
}

Luego, cuando necesites cambiar las restricciones, simplemente puedes pasar un ConstraintSet diferente.

Más información

Obtén más información sobre ConstraintLayout en Compose, en la sección de Diseño de restricciones correspondiente a los Diseños que se encuentran en el codelab de Jetpack Compose y consulta los ejemplos de Compose que usan ConstraintLayout para ver las API en acción.