Issue
I am trying to fire some Boxes regularly from bottom to top. I have almost managed to achieve this but for some reason my Boxes are not spaced evenly, as you can see from the gif. My feeling is that my code is not the best way to achieve what I am trying to do. Does anyone have any ideas?
Here is my code:
listOf(
Color(0xffDFFF00),
Color(0xffFFBF00),
Color(0xffFF7F50),
Color(0xffDE3163),
Color(0xff9FE2BF),
Color(0xff40E0D0),
Color(0xff6495ED),
Color(0xffCCCCFF),
).forEachIndexed { index, color ->
val infiniteTransition = rememberInfiniteTransition()
val positionState = infiniteTransition.animateFloat(
initialValue = 0f,
targetValue = 1f,
animationSpec = infiniteRepeatable(
animation = tween(
durationMillis = 2500,
delayMillis = delay,
easing = LinearEasing
)
)
)
delay += 1000
val modifier = Modifier.offset(
x = (maxWidth - tileSize),
y = maxHeight - (maxHeight * positionState.value),
)
Box(
modifier = modifier
.size(tileSize)
.clip(RoundedCornerShape(5.dp))
.background(color = color)
) {
Text(
text = text,
Modifier.align(Alignment.Center),
style = TextStyle(fontWeight = FontWeight.Bold)
)
}
Here is the gif:
PS: Having now tried the accepted answer, it doesn't work as expected. Please see comment below. Thanks!
Solution
This is because the delay
is also being repeated in the infiniteRepeatable
. In other words, the animations that were 1000ms apart in the first iteration become 2000ms apart in the second iteration.
Non-repeating delays are not yet support in infinite transition. Here I would recommend using Animatable
to achieved the staggered infinite animation.
...
forEachIndexed { index, color ->
val positionAnimation = remember { Animatable(0f) }
LaunchedEffect(positionAnimation) {
delay(1000 * index) // this delay increases with the index
launch {
positionAnimation.animateTo(
1f,
animationSpec = infiniteRepeatable(
animation = tween(
durationMillis = 2500, // remove the delay from infinite repeatable
easing = LinearEasing
)
)
)
}
}
...
Answered By - Doris Liu