Posts List
  1. 深坑详情
  2. 解决RotateAnimation旋转动画停顿现象

别被函数说明骗了!--走出setInterpolator的深坑

深坑详情

在使用RotateAnimation发现了这个问题。相信有很多人在使用RotateAnimation做旋转动画的时候都有过这样的问题,
就是动画旋转一周后,会有一段比较明显的停顿。于是,很多人没有深究其原因,通过将旋转角度设置为355而不是360这样的小技巧来弥补这个停顿时间,从而缓解了停顿感。

其实深究下来,这都是Interpolator的错。
仔细看,我们可以发现,动画的旋转过程其实是先加速,而后减速的。
所以由于开始的时候比较慢,结束的时候也比较慢,也就造成了动画在旋转快一周的时候有明显的停顿(其实只是动画变慢了而已)
但是setInterpolator函数却告诉我们,动画默认的interpolation是线性的,也就是说不存在先加速再减速的问题。

以下是setInterpolator的函数说明:

1
2
3
4
5
6
7
8
9
10
/**
* Sets the acceleration curve for this animation. Defaults to a linear
* interpolation.
*
* @param i The interpolator which defines the acceleration curve
* @attr ref android.R.styleable#Animation_interpolator
*/
public void setInterpolator(Interpolator i) {
mInterpolator = i;
}

虽然函数说明是说默认的Interpolator是linear interpolation,但是我只能说,别被骗了,以事实说话吧。
通过在Animation类中搜索mInterpolator,可以发现只有一个地方对mInterpolator进行赋值了。
那个函数就是ensureInterpolator。

1
2
3
4
5
6
7
8
9
/**
* Gurantees that this animation has an interpolator. Will use
* a AccelerateDecelerateInterpolator is nothing else was specified.
*/
protected void ensureInterpolator() {
if (mInterpolator == null) {
mInterpolator = new AccelerateDecelerateInterpolator();
}
}

从函数的实现中可以看到,当用户没有调用setInterpolator函数对mInterpolator进行初始化的时候,
ensureInterpolator会给mInterpolator赋值一个AccelerateDecelerateInterpolator
而这个,正是先加速,而后减速。也就是造成动画完成一个周期后产生停顿的原因。

解决RotateAnimation旋转动画停顿现象

所以,我们在使用RotateAnimation的时候,要想解决动画停顿的现象,只需要把Interpolator设置成线性的就可以了。

1
2
3
4
5
6
RotateAnimation anim = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5, Animation.RELATIVE_TO_SELF, 0.5);
// 显式的设置其Interpolator为LinearInterpolator
anim.setInterpolator(new LinearInterpolator());
anim.setRepeatCount(-1);
anim.setDuration(2000);
view.setAnimation(anim);

本文作者:JeremyHe
本文链接:https://alzz.me/posts/2014/08/05/06_别被函数说明骗了!--走出setInterpolator的深坑/
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!

联系作者
微信。◕‿◕。