Ive recently got into doing animations using jet pack compose and am wondering how you can make it so that when you increase a value in an offset, once the animation reaches that value it then changes the value to another value. So like update transition but instead of at the same time, one after the other.
3 Answers
Actually @RaBaKa's answer is partially correct, but it's missing information about how the animation should be run.
It should be done as a side effect. For example, you can use LaunchedEffect
: it is already running in a coroutine scope. It is perfectly normal to run one animation after another - as soon as the first suspend function finishes, the second will be started:
val value = remember { Animatable(0f) }
LaunchedEffect(Unit) {
value.animateTo(
20f,
animationSpec = tween(2000),
)
value.animateTo(
10f,
animationSpec = tween(2000),
)
}
Text(value.value.toString())
If you want to do this in response to some action, such as pressing a button, you need to run the coroutine yourself. The main thing is to run the animations in the same coroutine so that they are chained.
val value = remember { Animatable(0f) }
val scope = rememberCoroutineScope()
Button(onClick = {
scope.launch {
value.animateTo(
20f,
animationSpec = tween(2000),
)
value.animateTo(
10f,
animationSpec = tween(2000),
)
}
}) {
}
Text(value.value.toString())

- 67,741
- 15
- 184
- 220
-
yeah the looks similar to what i did to get it working except i used the animate function – JScott Feb 08 '22 at 10:05
The correct answer is to use Kotlin coroutines. I managed to get it working fine. You have to use coroutines in order to launch the animations in the correct sequence like this:
animationRoutine.launch {
coroutineScope {
launch {
animate(
startingValue,
targetValue,
animationSpec = whatYouWant,
block = { value, _ -> whateverYouNeed = value }
)
}
launch {
animate(
initialValue,
targetValue,
animationSpec = whatYouWant,
block = { value, _ -> whateverYouNeed = value }
)
}
}
Each of launch scope launches everything in a non blocking way if you tell it to allowing you to run multiple animations at once at a lower level and to sequence the animations you add another coroutine for the next part of the animation.

- 1,984
- 1
- 17
- 29

- 109
- 10
Maybe you can use Animatable
val value = remember { Animatable(0f) } //Initial Value
Then in compose you can just use
value.animateTo(20f)
then
value.animateTo(10f)
For more information visit the official documentation

- 1,115
- 7
- 11
-
From what Ive found i think i might have to sequence the animation using coroutines, Im going to give it a go and see, i don't think you can do what you said, won't it just cancel the first animation immediately? – JScott Feb 07 '22 at 15:31
-
Yeah, it'll cancel if there is an animation running, have you tried keyframes?, does that help you?? – RaBaKa 78 Feb 07 '22 at 23:13
-
1I managed to get it working with coroutines, you can see my answer provided if it interests you thanks :D – JScott Feb 08 '22 at 10:02