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

上图为原问题实现的错误效果:每轮循环都会重复应用缓入,出现周期性顿挫
内容的提问来源于stack exchange,提问作者SMBiggs
相关产品推荐
相关产品推荐

