I'm trying to animate a composable changing width ...
# compose
u
I'm trying to animate a composable changing width and height using
animateBounds
Copy code
@Composable
private fun BlueBar(isExpanded: Boolean) {
    LookaheadScope {
        Box(
            modifier = Modifier
                .padding(16.dp)
                .animateBounds(this) <-------
                .padding(horizontal = 16.dp, vertical = 16.dp)
                .then(if (isExpanded) Modifier.fillMaxWidth() else Modifier.width(100.dp))
                .then(if (isExpanded) Modifier.height(32.dp) else Modifier.height(64.dp))
                .background(Color.Blue, MaterialTheme.shapes.extraLarge)
        )
    }
}
and there is this odd translation effect to it (see video) what's that about? I'm only changing width and height. How do I get rid of it?
v
Well, if you re-arrange your modifiers so that animateBounds would go only before the size changes- it will work as expected:
Copy code
@Composable
private fun BlueBar(isExpanded: Boolean) {
    LookaheadScope {
        Box(
            modifier = Modifier
                .padding(16.dp)
                .padding(horizontal = 16.dp, vertical = 16.dp)
                .background(Color.Blue, MaterialTheme.shapes.extraLarge)
                .animateBounds(this)
                .then(if (isExpanded) Modifier.fillMaxWidth() else Modifier.width(100.dp))
                .then(if (isExpanded) Modifier.height(32.dp) else Modifier.height(64.dp))
        )
    }
}
Sorry, late answer, but maybe still relevant
u
works thank you! although, do you have an idea why?
Copy code
LookaheadScope {
    Box(
        modifier = Modifier
            .padding(top = 16.dp)
            .background(Color.Blue, MaterialTheme.shapes.extraLarge)
            .animateBounds(this)
            .then(if (isExpanded) Modifier.fillMaxWidth() else Modifier.width(64.dp))
            .then(if (isExpanded) Modifier.height(32.dp) else Modifier.height(64.dp))
    )
}
^^this works
Copy code
LookaheadScope {
    Box(
        modifier = Modifier
            .padding(top = 16.dp)
            .animateBounds(this)
            .background(Color.Blue, MaterialTheme.shapes.extraLarge)
            .then(if (isExpanded) Modifier.fillMaxWidth() else Modifier.width(64.dp))
            .then(if (isExpanded) Modifier.height(32.dp) else Modifier.height(64.dp))
    )
}
this makes it translate so..why does coloring
background
give it translation I don't get
or rathe, say I want to animate offset from the neighbor via
padding(top=)
Copy code
LookaheadScope {
    Box(
        modifier = Modifier
            .background(Color.Blue, MaterialTheme.shapes.extraLarge)
            .animateBounds(this)
            .padding(top = if (isExpanded) 64.dp else 24.dp)
            .then(if (isExpanded) Modifier.fillMaxWidth() else Modifier.width(64.dp))
            .then(if (isExpanded) Modifier.height(32.dp) else Modifier.height(64.dp))
    )
}
since now the semantics is different, padding after background "grows" the colored surface, not offsets it
v
Because modifier order matters. In my solution - only the width/height modifiers are using the animated / interpolated size from animateBounds and the blue background uses the elements currently measured size. When you move the background as part of the animation interpolation after animateBounds, something (not sure what exactly) messes up the compose draw cycle of the background
u
okay what about the new requirement - is that possible? regardless the reasons of background position mattering
v
I'm not entirely sure, not at my PC, but I think that padding should also go above animateBounds 🤔
u
if they do, and change due to animation, then obviously it will just jump
(since bkacground needs to be above animteBounds)
v
Yeah it should jump. Padding is a dilema in this case
u
I noticed
animateBounds
has
modifier
argument