前言概要
在项目中遇到需要循环播放动画的需求。
鄙人在实现时没有用到流行的动画框架,原因是项目中动画需求较少,并不需要为简单的动画引入一个动画框架,譬如
lottie。
1. 需求
一个上下抖动的位移动画,向下和向上是两种位移加速度,如图:

2. 实现代码
这里用到AnimationSet所以不能repeat动画,只能用AnimationListener做一个比较hack的重复调用。
private fun createAnimation(context: Context, view: View): Animation {
return createAnimationNoListener(context).also { set ->
set.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationRepeat(animation: Animation?) {
}
override fun onAnimationEnd(animation: Animation?) {
view.startAnimation(createAnimationNoListener(context).also {
it.setAnimationListener(this)
})
}
override fun onAnimationStart(animation: Animation?) {
}
})
}
}
private fun createAnimationNoListener(context: Context): AnimationSet {
return AnimationSet(false).also {
val pxDistance = context.resources.getDimensionPixelSize(R.dimen.padding_6_normal).toFloat()
val downAnim = TranslateAnimation(0f, 0f, 0f, pxDistance).apply {
this.interpolator = AccelerateInterpolator()
this.duration = 400
}
val upAnim = TranslateAnimation(0f, 0f, pxDistance, 0f).apply {
this.interpolator = AccelerateDecelerateInterpolator()
this.duration = 400
this.startOffset = 400
}
it.addAnimation(downAnim)
it.addAnimation(upAnim)
}
}
3. 问题的出现
下面的代码并不能把一个执行动画的 view 给隐藏掉
//开启
view.startAnimation(createAnimation(view.contoxt, view))
//隐藏
view.clearAnimation()
view.visibility = View.GONE
4. 解决办法
先把AnimationListener设置为null,再隐藏,解决问题
view.animation?.setAnimationListener(null)
view.clearAnimation()
view.visibility = View.GONE
5. 实现效果
实际速度会比 gif 快一些
