# ConstraintLayout

## Functions summary

|---|---|
| `inline https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `@https://developer.android.com/reference/kotlin/androidx/compose/runtime/Composable https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayout.composable#ConstraintLayout(androidx.compose.ui.Modifier,kotlin.Int,androidx.compose.animation.core.AnimationSpec,kotlin.Function0,kotlin.Function1)( modifier: https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier, optimizationLevel: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html, animateChangesSpec: https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationSpec<https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-float/index.html>?, noinline finishedAnimationListener: (() -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html)?, crossinline content: @https://developer.android.com/reference/kotlin/androidx/compose/runtime/Composable https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutScope.() -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html )` Layout that positions its children according to the constraints between them. |
| `inline https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `@https://developer.android.com/reference/kotlin/androidx/compose/runtime/Composable https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayout.composable#ConstraintLayout(androidx.constraintlayout.compose.ConstraintSet,androidx.compose.ui.Modifier,kotlin.Int,androidx.compose.animation.core.AnimationSpec,kotlin.Function0,kotlin.Function0)( constraintSet: https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintSet, modifier: https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier, optimizationLevel: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html, animateChangesSpec: https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationSpec<https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-float/index.html>?, noinline finishedAnimationListener: (() -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html)?, crossinline content: @https://developer.android.com/reference/kotlin/androidx/compose/runtime/Composable () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html )` Layout that positions its children according to the constraints between them. |
| `inline https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `@https://developer.android.com/reference/kotlin/androidx/compose/runtime/Composable [ConstraintLayout](https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayout.composable#ConstraintLayout(androidx.compose.ui.Modifier,kotlin.Int,kotlin.Boolean,androidx.compose.animation.core.AnimationSpec,kotlin.Function0,kotlin.Function1))( modifier: https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier, optimizationLevel: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html, animateChanges: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html, animationSpec: https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationSpec<https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-float/index.html>, noinline finishedAnimationListener: (() -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html)?, crossinline content: @https://developer.android.com/reference/kotlin/androidx/compose/runtime/Composable https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutScope.() -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html )` **This function is deprecated.** Prefer version that takes a nullable AnimationSpec to animate changes. |
| `inline https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `@https://developer.android.com/reference/kotlin/androidx/compose/runtime/Composable [ConstraintLayout](https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayout.composable#ConstraintLayout(androidx.constraintlayout.compose.ConstraintSet,androidx.compose.ui.Modifier,kotlin.Int,kotlin.Boolean,androidx.compose.animation.core.AnimationSpec,kotlin.Function0,kotlin.Function0))( constraintSet: https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintSet, modifier: https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier, optimizationLevel: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html, animateChanges: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html, animationSpec: https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationSpec<https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-float/index.html>, noinline finishedAnimationListener: (() -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html)?, crossinline content: @https://developer.android.com/reference/kotlin/androidx/compose/runtime/Composable () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html )` **This function is deprecated.** Prefer version that takes a nullable AnimationSpec to animate changes. |

## Functions

### ConstraintLayout

Artifact: [androidx.constraintlayout:constraintlayout-compose](https://developer.android.com/jetpack/androidx/releases/constraintlayout) [View Source](https://cs.android.com/search?q=file:androidx/constraintlayout/compose/ConstraintLayout.kt+function:ConstraintLayout) Added in [1.1.2](https://developer.android.com/jetpack/androidx/releases/constraintlayout#1.1.2)

```
@Composable
inline fun ConstraintLayout(
    modifier: Modifier = Modifier,
    optimizationLevel: Int = Optimizer.OPTIMIZATION_STANDARD,
    animateChangesSpec: AnimationSpec<Float>? = null,
    noinline finishedAnimationListener: (() -> Unit)? = null,
    crossinline content: @Composable ConstraintLayoutScope.() -> Unit
): Unit
```

Layout that positions its children according to the constraints between them.

Constraints are defined within the content of this ConstraintLayout `https://developer.android.com/reference/kotlin/androidx/compose/runtime/Composable`.

Items in the layout that are to be constrained are initialized with `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutScope#createRef()`:

```kotlin
val textRef = createRef()
val imageRef = createRef()
```

You may also use `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutScope#createRefs()` to declare up to 16 items using the destructuring declaration pattern:

```kotlin
val (textRef, imageRef) = createRefs()
```

Individual constraints are defined with `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutScope#(androidx.compose.ui.Modifier).constrainAs(androidx.constraintlayout.compose.ConstrainedLayoutReference,kotlin.Function1)`, this will also bind the Composable to the given `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstrainedLayoutReference`.

So, a simple layout with a text in the middle and an image next to it may be declared like this (keep in mind, when using `center...`, `start` or `end` the layout direction will automatically change in RTL locales):

```kotlin
ConstraintLayout(Modifier.fillMaxSize()) {
    val (textRef, imageRef) = createRefs()
    Text(
        modifier = Modifier.constrainAs(textRef) {
            centerTo(parent)
        },
        text = "Hello, World!"
    )
    Image(
        modifier = Modifier.constrainAs(imageRef) {
            centerVerticallyTo(textRef)
            start.linkTo(textRef.end, margin = 8.dp)
        },
        imageVector = Icons.Default.Android,
        contentDescription = null
    )
}
```

See `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstrainScope` to learn more about how to constrain elements together.

## Helpers

You may also use helpers, a set of virtual (not shown on screen) components that provide special layout behaviors, you may find these in the `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutScope` with the '`create...`' prefix, a few of these are **Guidelines** , **Chains** and **Barriers**.

### Guidelines

Lines to which other `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstrainedLayoutReference`s may be constrained to, these are defined at either a fixed or percent position from an anchor of the ConstraintLayout parent (top, bottom, start, end, absoluteLeft, absoluteRight).

Example:

```kotlin
val (textRef) = createRefs()
val vG = createGuidelineFromStart(fraction = 0.3f)
Text(
    modifier = Modifier.constrainAs(textRef) {
        centerVerticallyTo(parent)
        centerAround(vG)
    },
    text = "Hello, World!"
)
```

See

- `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutBaseScope#createGuidelineFromTop(androidx.compose.ui.unit.Dp)`

- `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutBaseScope#createGuidelineFromBottom(androidx.compose.ui.unit.Dp)`

- `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutBaseScope#createGuidelineFromStart(androidx.compose.ui.unit.Dp)`

- `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutBaseScope#createGuidelineFromEnd(androidx.compose.ui.unit.Dp)`

- `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutBaseScope#createGuidelineFromAbsoluteLeft(androidx.compose.ui.unit.Dp)`

- `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutBaseScope#createGuidelineFromAbsoluteRight(androidx.compose.ui.unit.Dp)`

### Chains

Chains may be either horizontal or vertical, these, take a set of `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstrainedLayoutReference`s and create bi-directional constraints on each of them at the same orientation of the chain in the given order, meaning that an horizontal chain will create constraints between the start and end anchors.

The result, a layout that evenly distributes the space within its elements.

For example, to make a layout with three text elements distributed so that the spacing between them (and around them) is equal:

```kotlin
val (textRef0, textRef1, textRef2) = createRefs()
createHorizontalChain(textRef0, textRef1, textRef2, chainStyle = ChainStyle.Spread)

Text(modifier = Modifier.constrainAs(textRef0) {}, text = "Hello")
Text(modifier = Modifier.constrainAs(textRef1) {}, text = "Foo")
Text(modifier = Modifier.constrainAs(textRef2) {}, text = "Bar")
```

You may set margins within elements in a chain with `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutBaseScope#(androidx.constraintlayout.compose.LayoutReference).withChainParams(androidx.compose.ui.unit.Dp,androidx.compose.ui.unit.Dp,androidx.compose.ui.unit.Dp,androidx.compose.ui.unit.Dp,androidx.compose.ui.unit.Dp,androidx.compose.ui.unit.Dp,androidx.compose.ui.unit.Dp,androidx.compose.ui.unit.Dp,kotlin.Float)`:

```kotlin
val (textRef0, textRef1, textRef2) = createRefs()
createHorizontalChain(
    textRef0,
    textRef1.withChainParams(startMargin = 100.dp, endMargin = 100.dp),
    textRef2,
    chainStyle = ChainStyle.Spread
)

Text(modifier = Modifier.constrainAs(textRef0) {}, text = "Hello")
Text(modifier = Modifier.constrainAs(textRef1) {}, text = "Foo")
Text(modifier = Modifier.constrainAs(textRef2) {}, text = "Bar")
```

You can also change the way space is distributed, as chains have three different styles:

- `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ChainStyle#Spread()` Layouts are evenly distributed after margins are accounted for (the space around and between each item is even). This is the **default** style for chains.

- `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ChainStyle#SpreadInside()` The first and last layouts are affixed to each end of the chain, and the rest of the items are evenly distributed (after margins are accounted for). I.e.: Items are spread from the inside, distributing the space between them with no space around the first and last items.

- `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ChainStyle#Packed(kotlin.Float)` The layouts are packed together after margins are accounted for, by default, they're packed together at the middle, you can change this behavior with the **bias** parameter of `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ChainStyle#Packed(kotlin.Float)`.

- Alternatively, you can make every Layout in the chain to be `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/Dimension#fillToConstraints()` and then set a particular weight to each of them to create a **weighted chain**.

#### Weighted Chain

Weighted chains are useful when you want the size of the elements to depend on the remaining size of the chain. As opposed to just distributing the space around and/or in-between the items.

For example, to create a layout with three text elements in a row where each element takes the exact same size regardless of content, you can use a simple weighted chain where each item has the same weight:

```kotlin
val (textRef0, textRef1, textRef2) = createRefs()
createHorizontalChain(
    textRef0.withChainParams(weight = 1f),
    textRef1.withChainParams(weight = 1f),
    textRef2.withChainParams(weight = 1f),
    chainStyle = ChainStyle.Spread
)

Text(modifier = Modifier.background(Color.Cyan).constrainAs(textRef0) {
    width = Dimension.fillToConstraints
}, text = "Hello, World!")
Text(modifier = Modifier.background(Color.Red).constrainAs(textRef1) {
    width = Dimension.fillToConstraints
}, text = "Foo")
Text(modifier = Modifier.background(Color.Cyan).constrainAs(textRef2) {
    width = Dimension.fillToConstraints
}, text = "This text is six words long")
```

This way, the texts will horizontally occupy the same space even if one of them is significantly larger than the others.

Keep in mind that chains have a relatively high performance cost. For example, if you plan on having multiple chains one below the other, consider instead, applying just one chain and using it as a reference to constrain all other elements to the ones that match their position in that one chain. It may provide increased performance with no significant changes in the layout output.

Alternatively, consider if other helpers such as `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutBaseScope#createGrid(kotlin.Array,kotlin.Int,kotlin.Int,kotlin.Boolean,androidx.compose.ui.unit.Dp,androidx.compose.ui.unit.Dp,kotlin.FloatArray,kotlin.FloatArray,kotlin.Array,kotlin.Array,androidx.constraintlayout.compose.GridFlag)` can accomplish the same layout.

See

- `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutBaseScope#createHorizontalChain(kotlin.Array,androidx.constraintlayout.compose.ChainStyle)`

- `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutBaseScope#createVerticalChain(kotlin.Array,androidx.constraintlayout.compose.ChainStyle)`

- `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutBaseScope#(androidx.constraintlayout.compose.LayoutReference).withChainParams(androidx.compose.ui.unit.Dp,androidx.compose.ui.unit.Dp,androidx.compose.ui.unit.Dp,androidx.compose.ui.unit.Dp,androidx.compose.ui.unit.Dp,androidx.compose.ui.unit.Dp,androidx.compose.ui.unit.Dp,androidx.compose.ui.unit.Dp,kotlin.Float)`

### Barriers

Barriers take a set of `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstrainedLayoutReference`s and creates the most further point in a given direction where other `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstrainedLayoutReference` can constrain to.

This is useful in situations where elements in a layout may have different sizes but you want to always constrain to the largest item, for example, if you have a text element on top of another and want an image to always be constrained to the end of them:

```kotlin
val (textRef0, textRef1, imageRef) = createRefs()

// Creates a point at the furthest end anchor from the elements in the barrier
val endTextsBarrier = createEndBarrier(textRef0, textRef1)

Text(
    modifier = Modifier.constrainAs(textRef0) {
        centerTo(parent)
    },
    text = "Hello, World!"
)
Text(
    modifier = Modifier.constrainAs(textRef1) {
        top.linkTo(textRef0.bottom)
        start.linkTo(textRef0.start)
    },
    text = "Foo Bar"
)
Image(
    modifier = Modifier.constrainAs(imageRef) {
        top.linkTo(textRef0.top)
        bottom.linkTo(textRef1.bottom)

        // Image will always be at the end of both texts, regardless of their size
        start.linkTo(endTextsBarrier, margin = 8.dp)
    },
    imageVector = Icons.Default.Android,
    contentDescription = null
)
```

Be careful not to constrain a `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstrainedLayoutReference` to a barrier that references it or that depends on it indirectly. This creates a cyclic dependency that results in unsupported layout behavior.

See

- `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutBaseScope#createTopBarrier(kotlin.Array,androidx.compose.ui.unit.Dp)`

- `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutBaseScope#createBottomBarrier(kotlin.Array,androidx.compose.ui.unit.Dp)`

- `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutBaseScope#createStartBarrier(kotlin.Array,androidx.compose.ui.unit.Dp)`

- `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutBaseScope#createEndBarrier(kotlin.Array,androidx.compose.ui.unit.Dp)`

- `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutBaseScope#createAbsoluteLeftBarrier(kotlin.Array,androidx.compose.ui.unit.Dp)`

- `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutBaseScope#createAbsoluteRightBarrier(kotlin.Array,androidx.compose.ui.unit.Dp)`

**Tip** : If you notice that you are creating many different constraints based on `https://developer.android.com/reference/kotlin/androidx/compose/runtime/State` variables or configuration changes, consider using the `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintSet` pattern instead, makes it clearer to distinguish different layouts and allows you to automatically animate the layout when the provided `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintSet` is different.

| Parameters |
|---|---|
| `modifier: https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier = Modifier` | Modifier to apply to this layout node. |
| `optimizationLevel: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html = Optimizer.OPTIMIZATION_STANDARD` | Optimization flags for ConstraintLayout. The default is `https://developer.android.com/reference/kotlin/androidx/constraintlayout/core/widgets/Optimizer#OPTIMIZATION_STANDARD()`. |
| `animateChangesSpec: https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationSpec<https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-float/index.html>? = null` | Null by default. Otherwise, ConstraintLayout will animate the layout if there were any changes on the constraints during recomposition using the given `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationSpec`. If there's a change while the layout is still animating, the current animation will complete before animating to the latest changes. For more control in the animation consider using `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/MotionLayout.composable#MotionLayout(androidx.constraintlayout.compose.ConstraintSet,androidx.constraintlayout.compose.ConstraintSet,kotlin.Float,androidx.compose.ui.Modifier,androidx.constraintlayout.compose.Transition,androidx.constraintlayout.compose.DebugFlags,kotlin.Int,androidx.constraintlayout.compose.InvalidationStrategy,kotlin.Function1)` instead. |
| `noinline finishedAnimationListener: (() -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html)? = null` | Lambda called whenever an animation due to `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/package-summary#ConstraintLayout(androidx.compose.ui.Modifier,kotlin.Int,androidx.compose.animation.core.AnimationSpec,kotlin.Function0,kotlin.Function1)` finishes. |
| `crossinline content: @https://developer.android.com/reference/kotlin/androidx/compose/runtime/Composable https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutScope.() -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | Content of this layout node. |

### ConstraintLayout

Artifact: [androidx.constraintlayout:constraintlayout-compose](https://developer.android.com/jetpack/androidx/releases/constraintlayout) [View Source](https://cs.android.com/search?q=file:androidx/constraintlayout/compose/ConstraintLayout.kt+function:ConstraintLayout) Added in [1.1.2](https://developer.android.com/jetpack/androidx/releases/constraintlayout#1.1.2)

```
@Composable
inline fun ConstraintLayout(
    constraintSet: ConstraintSet,
    modifier: Modifier = Modifier,
    optimizationLevel: Int = Optimizer.OPTIMIZATION_STANDARD,
    animateChangesSpec: AnimationSpec<Float>? = null,
    noinline finishedAnimationListener: (() -> Unit)? = null,
    crossinline content: @Composable () -> Unit
): Unit
```

Layout that positions its children according to the constraints between them.

This `https://developer.android.com/reference/kotlin/androidx/compose/runtime/Composable` of `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayout.composable#ConstraintLayout(androidx.constraintlayout.compose.ConstraintSet,androidx.compose.ui.Modifier,kotlin.Int,androidx.compose.animation.core.AnimationSpec,kotlin.Function0,kotlin.Function0)` takes a `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintSet` where the layout is defined using references and constraints.

Layouts referenced in the given `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/package-summary#ConstraintLayout(androidx.constraintlayout.compose.ConstraintSet,androidx.compose.ui.Modifier,kotlin.Int,androidx.compose.animation.core.AnimationSpec,kotlin.Function0,kotlin.Function0)` can be bound to immediate child Composables using `https://developer.android.com/reference/kotlin/androidx/compose/ui/layout/layoutId.modifier#(androidx.compose.ui.Modifier).layoutId(kotlin.Any)`, where the given layoutIds match each named reference.

So, a simple layout with a text in the middle and an image next to it may be declared like this:

```kotlin
// IDs
val textId = "text"
val imageId = "image"

// Layout definition with references and constraints
val constraintSet = remember {
    ConstraintSet {
        val (textRef, imageRef) = createRefsFor(textId, imageId)
        constrain(textRef) {
            centerTo(parent)
        }
        constrain(imageRef) {
            centerVerticallyTo(textRef)
            start.linkTo(textRef.end, margin = 8.dp)
        }
    }
}

// ConstraintLayout uses our given ConstraintSet
ConstraintLayout(
    constraintSet = constraintSet,
    modifier = Modifier.fillMaxSize()
) {
    // References are bound to Composables using Modifier.layoutId(Any)
    Text(
        modifier = Modifier.layoutId(textId),
        text = "Hello, World!"
    )
    Image(
        modifier = Modifier.layoutId(imageId),
        imageVector = Icons.Default.Android,
        contentDescription = null
    )
}
```

See `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintSet` to learn more on how to declare layouts using constraints.

### Handling of ConstraintSet objects

You typically want to *`remember`* declared `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintSet`s, to avoid unnecessary allocations on recomposition, if the `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintSetScope` block consumes any `https://developer.android.com/reference/kotlin/androidx/compose/runtime/State` variables, then something like *`remember { derivedStateOf { ConstraintSet { ... } } }`* would be more appropriate.

However, note in the example above that our ConstraintSet is constant, so we can declare it at a top level, improving overall Composition performance:

```kotlin
private const val TEXT_ID = "text"
private const val IMAGE_ID = "image"
private val mConstraintSet by lazy(LazyThreadSafetyMode.NONE) {
    ConstraintSet {
        val (textRef, imageRef) = createRefsFor(TEXT_ID, IMAGE_ID)
        constrain(textRef) {
            centerTo(parent)
        }
        constrain(imageRef) {
            centerVerticallyTo(textRef)
            start.linkTo(textRef.end, margin = 8.dp)
        }
    }
}

@Preview
@Composable
fun ConstraintSetExample() {
    ConstraintLayout(
        constraintSet = mConstraintSet,
        modifier = Modifier.fillMaxSize()
    ) {
        Text(
            modifier = Modifier.layoutId(TEXT_ID),
            text = "Hello, World!"
        )
        Image(
            modifier = Modifier.layoutId(IMAGE_ID),
            imageVector = Icons.Default.Android,
            contentDescription = null
        )
    }
}
```

This pattern (as opposed to defining constraints with `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayoutScope#(androidx.compose.ui.Modifier).constrainAs(androidx.constraintlayout.compose.ConstrainedLayoutReference,kotlin.Function1)`) is preferred when you want different layouts to be produced on different `https://developer.android.com/reference/kotlin/androidx/compose/runtime/State` variables or configuration changes. As it makes it easier to create distinguishable layouts, for example when building adaptive layouts based on Window size class:

```kotlin
private const val NAV_BAR_ID = "navBar"
private const val CONTENT_ID = "content"

private val compactConstraintSet by lazy(LazyThreadSafetyMode.NONE) {
    ConstraintSet {
        val (navBarRef, contentRef) = createRefsFor(NAV_BAR_ID, CONTENT_ID)

        // Navigation bar at the bottom for Compact devices
        constrain(navBarRef) {
            width = Dimension.percent(1f)
            height = 40.dp.asDimension()
            bottom.linkTo(parent.bottom)
        }

        constrain(contentRef) {
            width = Dimension.percent(1f)
            height = Dimension.fillToConstraints

            top.linkTo(parent.top)
            bottom.linkTo(navBarRef.top)
        }
    }
}

private val mediumConstraintSet by lazy(LazyThreadSafetyMode.NONE) {
    ConstraintSet {
        val (navBarRef, contentRef) = createRefsFor(NAV_BAR_ID, CONTENT_ID)

        // Navigation bar at the start on Medium class devices
        constrain(navBarRef) {
            width = 40.dp.asDimension()
            height = Dimension.percent(1f)

            start.linkTo(parent.start)
        }

        constrain(contentRef) {
            width = Dimension.fillToConstraints
            height = Dimension.percent(1f)

            start.linkTo(navBarRef.end)
            end.linkTo(parent.end)
        }
    }
}

@Composable
fun MyAdaptiveLayout(
    windowWidthSizeClass: WindowWidthSizeClass
) {
    val constraintSet = if (windowWidthSizeClass == WindowWidthSizeClass.Compact) {
        compactConstraintSet
    }
    else {
        mediumConstraintSet
    }
    ConstraintLayout(
        constraintSet = constraintSet,
        modifier = Modifier.fillMaxSize()
    ) {
        Box(Modifier.background(Color.Blue).layoutId(NAV_BAR_ID))
        Box(Modifier.background(Color.Red).layoutId(CONTENT_ID))
    }
}
```

### Animate Changes

When using multiple discrete `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintSet`s, you may pass non-null object to `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/package-summary#ConstraintLayout(androidx.constraintlayout.compose.ConstraintSet,androidx.compose.ui.Modifier,kotlin.Int,androidx.compose.animation.core.AnimationSpec,kotlin.Function0,kotlin.Function0)`. With this, whenever ConstraintLayout is recomposed with a different `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintSet` (by equality), it will animate all its children using the given `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationSpec`.

On the example above, using `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/package-summary#ConstraintLayout(androidx.constraintlayout.compose.ConstraintSet,androidx.compose.ui.Modifier,kotlin.Int,androidx.compose.animation.core.AnimationSpec,kotlin.Function0,kotlin.Function0)` would result on the layout being animated when the device changes to non-compact window class, typical behavior in some Foldable devices.

If more control is needed, we recommend using `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/MotionLayout.composable#MotionLayout(androidx.constraintlayout.compose.ConstraintSet,androidx.constraintlayout.compose.ConstraintSet,kotlin.Float,androidx.compose.ui.Modifier,androidx.constraintlayout.compose.Transition,androidx.constraintlayout.compose.DebugFlags,kotlin.Int,androidx.constraintlayout.compose.InvalidationStrategy,kotlin.Function1)` instead, which has a very similar pattern through the `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/MotionScene` object.

| Parameters |
|---|---|
| `constraintSet: https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintSet` | The `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintSet` that describes the expected layout, defined references should be bound to Composables with `https://developer.android.com/reference/kotlin/androidx/compose/ui/layout/layoutId.modifier#(androidx.compose.ui.Modifier).layoutId(kotlin.Any)`. |
| `modifier: https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier = Modifier` | Modifier to apply to this layout node. |
| `optimizationLevel: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html = Optimizer.OPTIMIZATION_STANDARD` | Optimization flags for ConstraintLayout. The default is `https://developer.android.com/reference/kotlin/androidx/constraintlayout/core/widgets/Optimizer#OPTIMIZATION_STANDARD()`. |
| `animateChangesSpec: https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationSpec<https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-float/index.html>? = null` | Null by default. Otherwise, ConstraintLayout will animate the layout if a different `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintSet` is provided on recomposition using the given `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationSpec`. If there's a change in `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintSet` while the layout is still animating, the current animation will complete before animating to the latest changes. For more control in the animation consider using `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/MotionLayout.composable#MotionLayout(androidx.constraintlayout.compose.ConstraintSet,androidx.constraintlayout.compose.ConstraintSet,kotlin.Float,androidx.compose.ui.Modifier,androidx.constraintlayout.compose.Transition,androidx.constraintlayout.compose.DebugFlags,kotlin.Int,androidx.constraintlayout.compose.InvalidationStrategy,kotlin.Function1)` instead. |
| `noinline finishedAnimationListener: (() -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html)? = null` | Lambda called whenever an animation due to `https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/package-summary#ConstraintLayout(androidx.constraintlayout.compose.ConstraintSet,androidx.compose.ui.Modifier,kotlin.Int,androidx.compose.animation.core.AnimationSpec,kotlin.Function0,kotlin.Function0)` finishes. |
| `crossinline content: @https://developer.android.com/reference/kotlin/androidx/compose/runtime/Composable () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | Content of this layout node. |

### ConstraintLayout

Artifact: [androidx.constraintlayout:constraintlayout-compose](https://developer.android.com/jetpack/androidx/releases/constraintlayout) [View Source](https://cs.android.com/search?q=file:androidx/constraintlayout/compose/ConstraintLayout.kt+function:ConstraintLayout) Added in [1.1.2](https://developer.android.com/jetpack/androidx/releases/constraintlayout#1.1.2) Deprecated in [1.1.2](https://developer.android.com/jetpack/androidx/releases/constraintlayout#1.1.2)

```
@Composable
inline fun [ConstraintLayout](https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayout.composable#ConstraintLayout(androidx.compose.ui.Modifier,kotlin.Int,kotlin.Boolean,androidx.compose.animation.core.AnimationSpec,kotlin.Function0,kotlin.Function1))(
    modifier: Modifier = Modifier,
    optimizationLevel: Int = Optimizer.OPTIMIZATION_STANDARD,
    animateChanges: Boolean = false,
    animationSpec: AnimationSpec<Float> = tween<Float>(),
    noinline finishedAnimationListener: (() -> Unit)? = null,
    crossinline content: @Composable ConstraintLayoutScope.() -> Unit
): Unit
```

> [!CAUTION]
> **This function is deprecated.**   
> Prefer version that takes a nullable AnimationSpec to animate changes, use this instead:
>
> ```kotlin
> ConstraintLayout(modifier = modifier, optimizationLevel = optimizationLevel, animateChangesSpec = animationSpec, finishedAnimationListener = finishedAnimationListener) { content() }
> ```

### ConstraintLayout

Artifact: [androidx.constraintlayout:constraintlayout-compose](https://developer.android.com/jetpack/androidx/releases/constraintlayout) [View Source](https://cs.android.com/search?q=file:androidx/constraintlayout/compose/ConstraintLayout.kt+function:ConstraintLayout) Added in [1.1.2](https://developer.android.com/jetpack/androidx/releases/constraintlayout#1.1.2) Deprecated in [1.1.2](https://developer.android.com/jetpack/androidx/releases/constraintlayout#1.1.2)

```
@Composable
inline fun [ConstraintLayout](https://developer.android.com/reference/kotlin/androidx/constraintlayout/compose/ConstraintLayout.composable#ConstraintLayout(androidx.constraintlayout.compose.ConstraintSet,androidx.compose.ui.Modifier,kotlin.Int,kotlin.Boolean,androidx.compose.animation.core.AnimationSpec,kotlin.Function0,kotlin.Function0))(
    constraintSet: ConstraintSet,
    modifier: Modifier = Modifier,
    optimizationLevel: Int = Optimizer.OPTIMIZATION_STANDARD,
    animateChanges: Boolean = false,
    animationSpec: AnimationSpec<Float> = tween<Float>(),
    noinline finishedAnimationListener: (() -> Unit)? = null,
    crossinline content: @Composable () -> Unit
): Unit
```

> [!CAUTION]
> **This function is deprecated.**   
> Prefer version that takes a nullable AnimationSpec to animate changes, use this instead:
>
> ```kotlin
> ConstraintLayout(constraintSet = constraintSet, modifier = modifier, optimizationLevel = optimizationLevel, animateChangesSpec = animationSpec, finishedAnimationListener = finishedAnimationListener) { content() }
> ```