Android:如何为View数组设置仅初始生效的偏移重复动画
解决View数组初始延迟动画、后续重复同步的问题
这个问题我之前也碰到过!用setStartOffset()确实会踩这个坑——因为它会在每一次动画循环(包括重复播放)前都等待设定的时间,导致动画越跑越不同步。要实现「仅初始阶段有延迟,后续重复时所有View同步」的效果,我们可以把初始单次动画和后续重复动画分开处理,具体方案如下:
核心思路
给每个View先播放一次带初始延迟的单次动画,当这次动画结束后,立即给该View启动一个无延迟、无限重复的动画。这样初始阶段每个View按顺序启动,之后所有View的重复动画就会完全同步了。
代码示例(Kotlin)
1. 定义动画创建方法
先封装两个动画:一个用于初始阶段的带延迟单次动画,另一个用于后续的无延迟重复动画:
import android.animation.Animator import android.animation.AnimatorListenerAdapter import android.animation.ObjectAnimator import android.view.View // 创建无延迟的无限重复动画 fun createRepeatingAnimator(): ObjectAnimator { return ObjectAnimator.ofFloat(View.SCALE_X, 1f, 0.8f, 1f).apply { duration = 500 // 动画时长 repeatCount = ObjectAnimator.INFINITE // 无限重复 repeatMode = ObjectAnimator.REVERSE // 反向重复 startOffset = 0 // 重复时无延迟 } } // 创建带初始延迟的单次动画,结束后触发回调 fun createInitialAnimator(view: View, delay: Long, onAnimationEnd: () -> Unit): ObjectAnimator { return ObjectAnimator.ofFloat(view, View.SCALE_X, 1f, 0.8f, 1f).apply { duration = 500 startOffset = delay // 仅初始阶段的延迟 addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator?) { super.onAnimationEnd(animation) onAnimationEnd() animation?.removeListener(this) // 移除监听避免内存泄漏 } }) } }
2. 给View数组应用动画
遍历你的View数组,给每个View依次设置初始动画和后续重复动画:
val yourViews: List<View> = listOf(view1, view2, view3) // 你的View集合 yourViews.forEachIndexed { index, view -> val initialAnimator = createInitialAnimator(view, index * 100L) { // 初始动画结束后,启动重复动画 createRepeatingAnimator().apply { target = view start() } } initialAnimator.target = view initialAnimator.start() }
另一种简化方案(ViewPropertyAnimator)
如果用ViewPropertyAnimator的话,代码会更简洁,逻辑是一样的:
yourViews.forEachIndexed { index, view -> // 初始带延迟的单次动画 view.animate() .scaleX(0.8f) .scaleY(0.8f) .setDuration(250) .setStartDelay(index * 100L) .withEndAction { // 启动无延迟的无限重复动画 view.animate() .scaleX(0.8f) .scaleY(0.8f) .setDuration(500) .setRepeatCount(ObjectAnimator.INFINITE) .setRepeatMode(ObjectAnimator.REVERSE) .start() } }
为什么这个方案可行?
- 初始动画的
startOffset只作用一次,保证每个View按顺序启动; - 后续的重复动画没有设置
startOffset,所有View的重复循环会完全同步,不会再出现延迟叠加的问题。
内容的提问来源于stack exchange,提问作者Ron Cohen
相关产品推荐
相关产品推荐

