You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose波浪文字动画:序列错乱问题求助

问题根源

你当前的动画错乱问题,核心在于tween的delayMillis仅在第一次动画周期启动时生效。当infiniteRepeatable进入反向或重复循环时,这个延迟不会再次触发,导致后续循环中字母的动画同步逻辑失效,不再保持依次缩放的顺序。

解决方案

以下两种方法均可解决该问题,推荐第二种,更易于调整整体动画节奏:

方法1:用keyframes嵌入循环内的延迟逻辑

将每个字母的延迟、缩放、反向逻辑全部写入关键帧,确保每次循环都严格遵循顺序:

@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 totalCycleDuration = duration * 2 // 正向放大+反向缩小的总时长
            val initialDelay = delayPerItem * index
            
            val scale by transition.animateFloat(
                initialValue = 1f,
                targetValue = 1f, // 关键帧会覆盖最终值,此处填初始值即可
                animationSpec = infiniteRepeatable(
                    animation = keyframes {
                        durationMillis = totalCycleDuration.toInt()
                        // 正向阶段:先等待对应延迟,再放大到2f
                        1f at initialDelay.toInt()
                        2f at (initialDelay + duration).toInt()
                        // 反向阶段:保持放大状态到周期中点,再缩小回1f
                        2f at (totalCycleDuration / 2 + initialDelay).toInt()
                        1f at (totalCycleDuration + initialDelay).toInt()
                    },
                    repeatMode = RepeatMode.Restart
                ), label = ""
            )
            Text(text = c.toString(), fontSize = (24 * scale).sp)
        }
    }
}

方法2:基于全局进度控制单个字母动画

创建一个全局循环进度,每个字母根据自身索引计算偏移后的进度,再映射到缩放值,逻辑更统一可控:

@Composable
fun AnimatedText(word: String) {
    val duration = 500L
    val delayPerItem = 100L
    val transition = rememberInfiniteTransition()
    
    // 总周期:覆盖所有字母完成一次放大+缩小的时长
    val totalCycle = duration * 2 + delayPerItem * (word.length - 1)
    val progress by transition.animateFloat(
        initialValue = 0f,
        targetValue = 1f,
        animationSpec = infiniteRepeatable(
            animation = tween(totalCycle.toInt(), easing = LinearEasing),
            repeatMode = RepeatMode.Restart
        ), label = ""
    )

    Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
        word.forEachIndexed { index, c ->
            // 计算当前字母的进度(减去自身延迟偏移)
            val letterProgress = (progress * totalCycle - delayPerItem * index)
                .coerceAtLeast(0f) / (duration * 2)
            
            // 映射进度到缩放值:0→1f(放大),0.5→2f,1→1f(缩小)
            val scale = when {
                letterProgress <= 0.5f -> 1f + letterProgress * 2f
                else -> 2f - (letterProgress - 0.5f) * 2f
            }.coerceIn(1f, 2f)

            Text(text = c.toString(), fontSize = (24 * scale).sp)
        }
    }
}

内容的提问来源于stack exchange,提问作者Oleksandr Myronchuk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 03:42:04