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

Jetpack Compose如何实现仅首次缓入的无限循环动画

问题原因

你当前的写法出现每轮循环重复缓入的核心原因是:infiniteRepeatable 会对每一个重复周期都完整应用传入的动画配置,包括你设置的EaseInCubic缓动曲线,官方没有提供单独配置首个周期动画参数的能力。

实现方案

不要直接在rememberInfiniteTransition里配置全周期的缓动,改用Animatable拆分两个动画阶段手动衔接,就能实现仅首次启动缓入、后续匀速循环的效果:

  • 第一阶段:仅执行1次的启动缓入段,使用EaseInCubic曲线完成第一圈的加速
  • 第二阶段:缓入完成后进入无限匀速循环段,使用LinearEasing保持转速恒定

完整实现代码

// 动画运行状态,由按钮点击触发修改
var isOrbiting by rememberSaveable { mutableStateOf(false) }
// 行星公转角度状态
val orbitRotation = remember { Animatable(initialValue = masterAngle) }

// 绑定运行状态启动动画
LaunchedEffect(isOrbiting, masterAngle) {
    if (!isOrbiting) {
        // 停止动画时回到初始角度,下次启动重新触发缓入
        orbitRotation.snapTo(masterAngle)
        return@LaunchedEffect
    }
    // 第一阶段:首次启动缓入,仅跑1圈
    orbitRotation.animateTo(
        targetValue = orbitRotation.value + 360f,
        animationSpec = tween(
            durationMillis = 3000,
            easing = EaseInCubic
        )
    )
    // 第二阶段:无限匀速循环,衔接上一段结束位置无跳变
    while (isOrbiting) {
        orbitRotation.animateTo(
            targetValue = orbitRotation.value + 360f,
            animationSpec = tween(
                durationMillis = 3000,
                easing = LinearEasing
            )
        )
    }
}

// 绘制行星时直接使用orbitRotation.value作为公转角度即可

效果说明

  • 点击按钮将isOrbiting设为true时,动画会从初始角度开始以缓入效果启动
  • 第一圈跑完后自动进入匀速旋转状态,不会再出现每圈重复减速-加速的顿挫
  • 再次点击按钮停止时会回到初始位置,下次启动重新触发缓入效果
  • 两段动画数值完全衔接,不会出现角度跳变

每3秒重复缓入的循环动画示例

上图为原问题实现的错误效果:每轮循环都会重复应用缓入,出现周期性顿挫


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 19:06:33