Reputation: 640
I am trying to create a layout in which the parent of the content has horizontal padding, but the divider between content items should ignore the padding on the right side.
To make it more clear, I made this drawing of what I want:
Now, I got something to work by using the Modifier.offset(x=16.dp)
and that did the trick except that now the divider is now too 'short' on the left side, like this:
How can I achieve such a layout? Thanks in advance!
Upvotes: 12
Views: 7738
Reputation: 1366
I would suggest to slightly amend the solution from Oya to use this.layout {}
instead of this.then(layout {})
:
fun Modifier.fillWidthOfParent(parentPadding: Dp) = this.layout { measurable, constraints ->
// This is to force layout to go beyond the borders of its parent
val placeable =
measurable.measure(constraints.copy(maxWidth = constraints.maxWidth + 2 * parentPadding.roundToPx()))
layout(placeable.width, placeable.height) {
placeable.place(0, 0)
}
}
In the original solution fillWidthOfParent
would call previous modifiers in chain twice. Commenting fillWidthOfParent
using this.then(layout {})
in the following reproducer will add additional vertical padding:
@Composable
@Preview(widthDp = 60, heightDp = 100)
fun TestPreview() {
Column(
modifier = Modifier
.background(Color.Gray)
.padding(10.dp)
) {
Text(
modifier = Modifier
.background(Color.Cyan)
.padding(bottom = 20.dp)
.fillWidthOfParent(10.dp) // Try commenting and uncommenting this line
,
text = "xxxxxxxxxx"
)
}
}
Without fillWidthOfParent |
fillWidthOfParent with this.layout {} |
fillWidthOfParent with this.then(layout {}) |
---|---|---|
![]() |
![]() |
![]() |
Upvotes: 2
Reputation: 2516
We have a few components in our grid that needs to go full width. Based on Gabriele's answer, I made this a reusable custom modifier:
fun Modifier.fillWidthOfParent(parentPadding: Dp) = this.then(
layout { measurable, constraints ->
// This is to force layout to go beyond the borders of its parent
val placeable = measurable.measure(
constraints.copy(
maxWidth = constraints.maxWidth + 2 * parentPadding.roundToPx(),
),
)
layout(placeable.width, placeable.height) {
placeable.place(0, 0)
}
},
)
When I want a component to bypass parent's padding and go full screen, I pass this modifier instead of fillMaxWidth(). The argument passed is the padding of the parent. You can assign it a default value if your app screen has consistent page margins (which is hopefully the case)
Upvotes: 13
Reputation: 364506
The offset
modifier doesn't work because you are just applying an offset without changing the width.
You can use the layout
modifier to specify the size and the position where the element should be placed.
Something like:
Divider(
color = Black,
modifier = Modifier
.layout(){ measurable, constraints ->
val placeable = measurable.measure(constraints.copy(
maxWidth = constraints.maxWidth + 16.dp.roundToPx(), //add the end padding 16.dp
))
layout(placeable.width, placeable.height) {
placeable.place(8.dp.roundToPx(), 0)
}
}
)
Upvotes: 19