I've been reading <https://android.googlesource.co...
# compose
k
I've been reading https://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/ui/ui-layout/samples/src/main/java/androidx/ui/layout/samples/SizeModifierSample.kt And I found it a little weird,
Copy code
@Composable
fun SimpleSizeModifier() {
    // The result is a 50.dp x 50.dp red box centered in a 100.dp x 100.dp space.
    // Note that although a previous modifier asked it to be 100.dp x 100.dp, this
    // will not be respected. They would be respected if preferredSize was used instead of size.
    Box(
        Modifier
            .size(100.dp, 100.dp)
            .size(50.dp, 50.dp),
        backgroundColor = Color.Red
    )
}
So it's another way of adding padding but instead of add a padding value we create some empty space and put a 50x50 box inside it. Am I right?
m
Yes, the effect here is a padding, but this is not necessarily the right way to think about it. What you see is the side effect of conflicting measurement.
The outer modifier asks the inner one to be exactly
100dp
size. Most layouts will respect the constraints coming from the wrapper, however, the inner
size
modifier will not respect them, and will set its size and the size of its content to be
50dp
. The effect is that the outer modifier will still be
100.dp
so the
100dp
space will still be occupied, the inner will be
50.dp
and because the constraints were not respected we fallback to centering the
50.dp
square inside the
100.dp
one. If you don't like centering, you can use
wrapContentSize
to choose the alignment.
Having a way to handle conflicting measurements is useful for components that have minimum size requirements, without which their layout does not make sense. For example, imagine a date picker being measured by its parent with
20.dp
available space 🙂
v
Does the first size modifier act as the upper limit to the second size modifier? i.e does this work similar to a parent to child constraint?
m
Yes, it is exactly a parent to child constraint - the provided
size
will be both lower and upper bound. However, the second size modifier is allowed not to respect the constraints - it could also be larger e.g.
Modifier.size(100.dp).size(150.dp)
would make the content
150.dp
and will be centered in a
100.dp
space. The layout parent of the layout with this modifier will see that the layout is 100.dp, not 150
v
oh interesting! This goes in my saved messages on slack 😄 Thanks for this example, does a great job answering my question!
k
@Mihai Popa Thank you for your nice explanation. Sorry for late response. I tried your last example:
Copy code
with(DensityAmbient.current) {
        Box(
            Modifier.drawBackground(Color.Green)
                .onPositioned {
                    Log.d("SizeModifiers", "onPositioned: ${it.size.width.toDp()}")
                }
                .onChildPositioned {
                    Log.d("SizeModifiers", "onChildPositioned: ${it.size.width.toDp()}")
                }
        ) {
            Box(
                Modifier
                    .size(100.dp, 100.dp)
                    .size(150.dp, 150.dp)
                    .drawBackground(Color.Yellow)
            )
        }
    }
SizeModifiers: onPositioned: 99.9061.dp
SizeModifiers: onChildPositioned: 150.23474.dp
Interesting! the the child is positioned as
150.dp
but the parent is positioned as
100.dp