'Single-Shot/Fire-and-Forget Animator for animating basic state changes (animate*AsState's single-shot equivalent))
I want to animate only once and I'm trying different options. I wanted to use animate*AsState but that doesn't work since you have to kind of trigger it by doing some kind of SideEffect with LaunchedEffect when entering in that screen like this:
@Composable
fun StartAnimation(width: Float = 0f) {
var startAnimation by remember { mutableStateOf(false) }
val widthAnimation = animateDpAsState(targetValue = if(startAnimation) width.dp else 0.dp, tween(600))
Box(
modifier = Modifier
.padding(top = 30.dp)
.padding(horizontal = 30.dp)
.fillMaxWidth()
.height(20.dp)
.background(Color.Gray),
contentAlignment = Alignment.CenterStart
) {
Box(
Modifier
.background(Color.Black)
.width(widthAnimation.value)
.height(20.dp)
.background(Color.Black)
)
}
LaunchedEffect(key1 = true) {
startAnimation = true
}
}
Maybe there's a better way to do this and I'm missing it?
Solution 1:[1]
Just create a custom fire-and-forget system. Works as a single-shot animator and can be spawned practically as many times as you like, in parallel.
@Composable
fun animateFloatAsState(
initialValue: Float,
targetValue: Float,
delay: Long = 0,
animationSpec: AnimationSpec<Float> = spring<Float>(),
visibilityThreshold: Float = 0.01f,
finishedListener: ((Float) -> Unit)? = null
): State<Float> {
var trigger by remember { mutableStateOf(false) }
return animateFloatAsState(
targetValue = if (trigger) targetValue else initialValue,
animationSpec = animationSpec,
visibilityThreshold = visibilityThreshold,
finishedListener = finishedListener
).also {
LaunchedEffect(Unit) {
delay(delay)
trigger = true
}
}
}
This is for Float, but can as easily be translated to fit Dp. I think it is just replacing the word Float with Dp
Solution 2:[2]
I don't think there is anything that will let you get rid of LaunchedEffect. But this might be better, at least you don't have to use that artificial variable:
val animatableWidth = remember { Animatable(0.dp, Dp.VectorConverter) }
LaunchedEffect(width) {
animatableWidth.animateTo(width.dp, tween(600))
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Jan BÃna |
