-
Notifications
You must be signed in to change notification settings - Fork 175
Compose ConstraintLayout DSL Syntax
A quick reference on how to implement some typical ConstraintLayout cases in Compose.
Both syntax work very much alike with a slight difference in setup.
val constraintSet = ConstraintSet {
val titleText = createRefFor("title")
// Helpers are defined in this scope
createStartBarrier(titleText)
constrain(titleText) {
// constraints, dimensions, transforms
}
}
ConstraintLayout(constraintSet) {
Text(text = "", modifier = Modifier.layoutId("title"))
}
ConstraintLayout {
val title = createRef()
// Helpers are defined in this scope
createStartBarrier(title)
Text(text = "", modifier = Modifier.constrainAs(title) {
// constraints, dimensions, transforms
})
}
- Note that only the immediate children Composables can be constrained
- Prefer ConstraintSet for more manageable and reusable Layouts
The available API under the ConstrainScope, ie:
constrain(createRefFor("id")) {
// The API here
}
Constrain a Composable to another using Anchorable.linkTo()
constrain(title) {
start.linkTo(parent.start, margin = 10.dp)
}
Or align a Composable with center...()
constrain(title) {
centerTo(parent) // Center around or inside the given reference
centerHorizontallyTo(parent, bias = 0.5f) // Constrain start & end to the same anchors at the given reference
centerVerticallyTo(parent, bias = 0.5f) // Constrain top & bottom to the same anchors at the given reference
}
Use androidx.constraintlayout.compose.Dimension to define the dimension behavior of a Composable.
constrain(title) {
width = Dimension.value(10.dp)
}
The typical use-cases:
- Dimension.value(Dp)
- Dimension.wrapContent
- Dimension.matchParent
- Dimension.fillToConstraints - Equivalent to "match_constraints" in the View system
See the Dimension interface documentation for more.
You can use Dimension.ratio(String) to define a dimension as a proportion to the other.
Where the String is a Width:Height ratio.
height = Dimension.value(10.dp)
width = Dimension.ratio("4:1") // The width will be 40dp
// ---------
width = Dimension.wrapContent
height = Dimension.ratio("1:0.25") // The height will be a fourth of the resulting wrapContent width
As with the View system, you can set the visibility of a Composable.
- Visibility.Visible - The default Visibility of Composables in ConstraintLayout
- Visibility.Invisible - Effectively the same as setting the alpha to 0.0f
- Visibility.Gone - The dimensions of the Composable will collapse to 0, and constraints will still be considered
Composables constrained to another with visibility Gone will use goneMargin instead:
constrain(title) {
visibility = Visibility.Gone
}
constrain(name) {
start.linkTo(title.end, margin = 4.dp, goneMargin = 8.dp) // The margin in the layout will be 8dp
}
Create horizontal and vertical chains by passing the ConstrainedLayoutReferences of each Composable that should be in the chain. The order each reference is passed will be reflected in the chain.
// text1 is the head (left-most element) of the chain
createHorizontalChain(text1, text2, button1, ChainStyle.Packed)
Additionally, chains can be constrained on their axis to reposition them (by default, they are constrained to the parent). Do not try to re-define the constraints for the elements in the chain, it will result in unexpected behavior.
// text1 start is constrained to parent.start, button1 end is constrained to parent.end
val chain1 = createHorizontalChain(text1, button1)
constrain(chain1) {
// text1 start will now be constrained to vGuideline1
start.linkTo(vGuideline1)
// button1 end will now be constrained to vGuideline2
end.linkTo(vGuideline2)
}
constraint(text1) {
// DO NOT DO THIS if you wish to constrain the chain to a different element
start.linkTo(vGuideline1)
// You can however, change the constrains on the axis not managed by the chain
top.linkTo(button1.bottom)
}
Guidelines can be created with respect to an anchor of the parent (the ConstraintLayout Composable).
- createGuidelineFromAbsoluteLeft
- createGuidelineFromStart
- createGuidelineFromAbsoluteRight
- createGuidelineFromEnd
- createGuidelineFromTop
- createGuidelineFromBottom
And can be defined as a distance from the anchor in Dp, or as a percentage of the total dimension on the respective axis.
// located at 10dp from the end anchor
val g1 = createGuidelineFromEnd(10.dp)
// located at 30% the distance of the total width from the end anchor
// Eg: for a ConstraintLayout with width of 100dp, the guideline will be at 30dp from the end
val g2 = createGuidelineFromEnd(0.3f)
Use barriers to be able to constrain to the outermost anchor within a group of elements.
// The barrier will act as an anchorable point that is always situated
// at the end-most point of text1 and text2 with an additional 2dp margin
val barrier1 = createEndBarrier(text1, text2, margin = 2.dp)
constrain(button1) {
// The barrier guarantees the button never overlaps with text1 or text2
start.linkTo(barrier1)
}
A barrier can be created for each anchor:
- createAbsoluteLeftBarrier
- createStartBarrier
- createAbsoluteRightBarrier
- createEndBarrier
- createTopBarrier
- createBottomBarrier