I am currently developing an application using Kotlin and Jetpack Compose. My task is to create an animation where each letter in a given word alternately increases and decreases in size, creating a wave-like effect across the text. This means that one letter at a time will grow larger, then shrink back to its original size, before the next letter does the same. This pattern will repeat for each letter in the word.
Here is the relevant code:
@Preview(showBackground = true)
@Composable
fun AnimatedTextPreview()
{
AnimatedText("Hello")
}
@Composable
fun AnimatedText(word: String) {
val duration = 500L
val delayPerItem = 100L
val transition = rememberInfiniteTransition()
Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
word.forEachIndexed { index, c ->
val scale by transition.animateFloat(
initialValue = 1f,
targetValue = 2f,
animationSpec = infiniteRepeatable(
animation = tween(
durationMillis = duration.toInt(),
delayMillis = ((delayPerItem * index) % duration).toInt(),
easing = FastOutSlowInEasing
),
repeatMode = RepeatMode.Reverse
), label = ""
)
Text(text = c.toString(), fontSize = (24 * scale).sp)
}
}
}
The animation sequence works as expected the first time, creating a wave effect as each letter increases and decreases. However, from the second time onwards, the letters start increasing and decreasing out of order, disrupting the animation. I suspect the issue might be with delayMillis.
I would appreciate any guidance on how to resolve this issue
infiniteRepeatable
repeats the animation along with the specified delay on each cycle, causing desynchronization after the initial cycle.
To avoid this, delay only the first iteration using initialStartOffset
parameter:
animationSpec = infiniteRepeatable(
animation = tween(
durationMillis = duration.toInt(),
easing = FastOutSlowInEasing
),
repeatMode = RepeatMode.Reverse,
initialStartOffset = StartOffset(offsetMillis = ((delayPerItem * index) % duration).toInt())
),
Note that your animation has to recompose one each frame, which may cause lags if your UI is complex. If you face such issue in release version of the app, you can draw letters on Canvas
- measure each letter once with maximum font size(48.sp
in this case), and scale/position them depending on animation state.