When I set my pleaceable constraint as below.
LazyColumn(
contentPadding = PaddingValues(all =64.dp),
verticalArrangement = Arrangement.spacedBy(16.dp),
) {
val adjust = 32.dp
item {
Divider(modifier = Modifier.height(20.dp))
}
item {
Divider(modifier = Modifier.height(20.dp)
.layout { measurable, constraints ->
val placeable =
// -32.dp offset constraint
measurable.measure(constraints.offset(-adjust.roundToPx()))
layout(placeable.width, placeable.height
) { placeable.place(0, 0) }
}
)
}
item {
Divider(modifier = Modifier.height(20.dp)
.layout { measurable, constraints ->
val placeable =
// +32.dp offset constraint
measurable.measure(constraints.offset(adjust.roundToPx()))
layout(placeable.width, placeable.height
) { placeable.place(0, 0) }
}
)
}
}
The 3 rows of items result (as shown in the image) below whereby
Why does the second and third-row behavior differs i.e. 2nd row shrink just on the right, while 3rd row expands on both side equally?
It's not exactly about adding or subtracting, these operations work as expected when they return values in min-max bounds of Constraints
.
It's because setting layout width/height a Composable out of Constraints
min-max bounds results it's being placed as the half of difference between Contraints
and the value used in layout()
function.
If the content chooses a size that does not satisfy the incoming Constraints, the parent layout will be reported a size coerced in the Constraints, and the position of the content will be automatically offset to be centered on the space assigned to the child by the parent layout under the assumption that Constraints were respected.
When layout width is bigger than constraints.maxWidth
(constraints.maxWidth-layout(width))/2
which means placed with offset to the left
when layout width is smaller than constraints.minWidth
(constraint.minWidth-layout(width))/2
which means placed with offset to the right.
You can refer this tutorial for more samples, information and examples about how layout, and Constraints work.
Also when you change as in snippet below it will be more clear to see how it works
@Preview
@Composable
private fun LayoutConstraintsSample1() {
val density = LocalDensity.current
LazyColumn(
modifier = Modifier
.padding(top = 40.dp)
.padding(horizontal = 40.dp)
.border(1.dp, Color.Red),
verticalArrangement = Arrangement.spacedBy(16.dp),
) {
val width = with(density) {
300f.toDp()
}
val adjust = 32.dp
item {
Divider(modifier = Modifier.height(20.dp))
}
item {
Divider(modifier = Modifier
.height(20.dp)
.layout { measurable, constraints ->
val placeable =
// -32.dp offset constraint
measurable.measure(constraints.offset(-adjust.roundToPx()))
layout(
placeable.width, placeable.height
) { placeable.place(0, 0) }
}
)
}
item {
Divider(modifier = Modifier
.width(width)
.height(20.dp)
.layout { measurable, constraints ->
val placeable =
measurable.measure(
constraints.copy(
minWidth = 300,
maxWidth = 300
)
)
layout(
200, placeable.height
) { placeable.place(0, 0) }
}
)
}
item {
Divider(modifier = Modifier
.width(width)
.height(20.dp)
.layout { measurable, constraints ->
val placeable =
measurable.measure(
constraints.copy(
minWidth = 300,
maxWidth = 300
)
)
layout(
400, placeable.height
) { placeable.place(0, 0) }
}
)
}
}
}
Placable width is same(300px) for both instances
@Preview
@Composable
private fun LayoutConstraintsSample2() {
val density = LocalDensity.current
LazyColumn(
modifier = Modifier
.padding(top = 40.dp)
.padding(horizontal = 40.dp)
.border(1.dp, Color.Red),
verticalArrangement = Arrangement.spacedBy(16.dp),
) {
val width = with(density) {
300f.toDp()
}
val adjust = 32.dp
item {
Divider(modifier = Modifier.height(20.dp))
}
item {
Divider(modifier = Modifier
.height(20.dp)
.layout { measurable, constraints ->
val placeable =
// -32.dp offset constraint
measurable.measure(constraints.offset(-adjust.roundToPx()))
layout(
placeable.width, placeable.height
) { placeable.place(0, 0) }
}
)
}
item {
Divider(modifier = Modifier
.width(width)
.height(20.dp)
.layout { measurable, constraints ->
val placeable =
measurable.measure(
constraints.copy(
minWidth = 300,
maxWidth = 300
)
)
layout(
200, placeable.height
) { placeable.place(0, 0) }
}
)
}
item {
Divider(modifier = Modifier
.width(width)
.height(20.dp)
.layout { measurable, constraints ->
val placeable =
measurable.measure(
constraints.copy(
minWidth = 300,
maxWidth = 300
)
)
layout(
400, placeable.height
) { placeable.place(0, 0) }
}
)
}
}
}