sindrenm
06/07/2023, 5:48 PMModifier.widthIn()
work when inside a horizontally scrollable container? I'm seeing some less-than-obvious-to-me behavior.
@Preview
@Composable
private fun Working() {
Row(Modifier.horizontalScroll(rememberScrollState()).padding(16.dp), Arrangement.spacedBy(12.dp)) {
repeat(2) {
Box(Modifier.width(300.dp).height(150.dp).background(Color.Red)) {
Box(Modifier.fillMaxSize().background(Color.Blue))
}
}
}
}
@Preview
@Composable
private fun Failing() {
Row(Modifier.horizontalScroll(rememberScrollState()).padding(16.dp), Arrangement.spacedBy(12.dp)) {
repeat(2) {
Box(Modifier.widthIn(300.dp).height(150.dp).background(Color.Red)) {
Box(Modifier.fillMaxSize().background(Color.Blue))
}
}
}
}
I would expect those two to produce the same result, as the only difference is the widthIn(min = 300.dp)
in the latter. However, the first one produces the expected blue box, and the second gives me a red box, as if the innermost `Box`'s Modifier.fillMaxSize()
didn't matter. Or is there something I'm just not getting here?Stylianos Gakis
06/07/2023, 7:48 PMhorizontalScroll
from the row above itStylianos Gakis
06/07/2023, 7:50 PMhorizontalScroll(rememberScrollState())
and not specifying specific max bounds.
Maybe somehow even though the min size is 300, since horizontalScroll expects all of its children to have a specified max height (since asking for “max” width doesn’t make sense for a container which has infinite width, since it’s scrollable.
And then somehow it decides that you know what? If I don’t know the max size, I won’t even give it a min size 😅
Not 100% how this interaction plays with each other, I am trying to read the docs of horizontalScroll now.Stylianos Gakis
06/07/2023, 8:53 PMRow(Modifier.horizontalScroll(rememberScrollState()).padding(16.dp), Arrangement.spacedBy(12.dp)) {
repeat(2) {
Box(Modifier.width(300.dp).height(150.dp).background(Color.Red)) {
Box(Modifier.fillMaxSize().background(Color.Blue))
BoxWithConstraints {
Text("${this.minWidth}|${this.maxWidth}")
}
}
}
}
You get this result:
Top (width) gives the child a range of 0 - 300
Bottom (widthIn) gives the child a range of 0 - infinityStylianos Gakis
06/07/2023, 8:58 PMpropagateMinConstraints = true
in your outer box, which would do exactly what it says, also give the min 300 width constraint to your child (not changing the max constraints
• Use Modifier.matchParentSize()
on that child component. Which will pass min and max constraints to be exactly 300, since the parent is in fact 300 in this case.
This works
Row(Modifier.horizontalScroll(rememberScrollState()).padding(16.dp), Arrangement.spacedBy(12.dp)) {
repeat(2) {
Box(Modifier.widthIn(300.dp).height(150.dp).background(Color.Red), propagateMinConstraints = true) {
Box(Modifier.fillMaxSize().background(Color.Blue))
}
}
}
And this works too
Row(Modifier.horizontalScroll(rememberScrollState()).padding(16.dp), Arrangement.spacedBy(12.dp)) {
repeat(2) {
Box(Modifier.widthIn(300.dp).height(150.dp).background(Color.Red)) {
Box(Modifier.matchParentSize().background(Color.Blue))
}
}
}
sindrenm
06/08/2023, 7:47 AMCard
, not a Box
. That matters because Card
does exactly what you suggest (through Surface
), and set propagateMinConstraints = true
. However, it wasn't enough for even deeper nesting, it seems.
Since matchParentSize()
is also on the BoxScope
, it's not something I would be able to use in this case, either. But I've had a chat with some of my team mates, and we've decided to actually roll with a set width
, and not let it expand horizontally, but rather grow vertically if needed. My use case was trying to avoid breaking some text if it was too long, but we decided to just break it.
Secondly, we were also using weight
further into the component, which was where the problem initially started.
Row(Modifier.horizontalScroll()) {
Box(Modifier.fillMaxWidth()) {
Row(Modifier.fillMaxWidth()) {
Stuff(Modifier.weight(1f))
OtherStuff(Modifier.size(100.dp))
}
}
}
Now, because the inner-most Row
there didn't get a proper max width constraint (which makes sense, as you say, because the top-level scrollable container is essentially infinitely wide), weight(1f)
gives a width of 0.dp
, as there's no excess left after OtherStuff
.Stylianos Gakis
06/08/2023, 7:57 AM