经过上一章的学习,我们已经学会了属性动画的基本使用,这一章里我们就来讲一讲属性动画的底层实现,简单讲一下什么是TimeInterpolator,什么是TypeEvaluator,以及它们是如何产生作用来呈现我们所看到的动画的。
Animator执行流程
我们从一个简单的例子来演示动画过程中的执行过程:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
animator = ValueAnimator.ofFloat(0,800);
animator.setDuration(2000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
ivContainer.setTranslationY((Float) animation.getAnimatedValue());
}
});
rgInterpolatorType.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
ivContainer.setTranslationY(0);
}
});
}
protected void valueAnalysis(View view) {
log = new StringBuilder("");
switch (rgInterpolatorType.getCheckedRadioButtonId()) {
case R.id.rb_type_linear:
animator.setInterpolator(new LinearInterpolator());//线性插值器
break;
case R.id.rb_type_accelerate_decelerate:
animator.setInterpolator(new AccelerateDecelerateInterpolator());//先加速后减速
break;
case R.id.rb_type_bounce:
animator.setInterpolator(new BounceInterpolator());//弹跳
break;
}
animator.start();
}
程序执行效果是这样:
可以看到分别使用了三种不同的的Interpolator后,动画执行效果有了不同,LinearInterpolator为匀速执行,每个时间片段内变化值相同,AccelerateDecelerateInterpolator则是先加速再减速,最后一个则有一个回弹的效果,为什么会这样呢,我们点开LinearInterpolator和AccelerateDecelerateInterpolator,可以看到有两个有趣的方法:
public float getInterpolation(float input) {
//LinearInterpolator
return input;
}
public float getInterpolation(float input) {
//AccelerateDecelerateInterpolator
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}
我们这里直接讲结论了,此方法在属性动画的使用中是接收一个时间因子(当前动画执行时间/动画时长),然后返回一个float值(0~1),代表动画从开始到结束,然后返回值会被传入TypeEvaluator的evaluate(float fraction, Object startValue, Object endValue)
方法中,充当第一个参数,然后根据开始值和结束值得出当前值(endValue - startValue)*fraction+startValue。这样也就不难理解AccelerateDecelerateInterpolator先加速后减速的原理了,看下余弦曲线π~2π的走势就可以很明了的知道了。BounceInterpolator由于我数学水平有限,就不献丑了,有兴趣的可以打开源码查看实现原理。
至此,我们已经明白一个动画的执行流程是如何的了。动画开始执行时,会动态的计算时间因子timeFraction(当前动画执行时间/动画时长),然后使用TimeInterpolator的getInterpolation方法得到一个合适的插值因子fraction,再由TypeEvaluator使用这个插值因子计算出当前的值(float、int、argb、object等),然后调用AnimatorUpdateListener的onAnimationUpdate方法,就可以取到当前的值了。而ObjectAnimator则是使用了反射的手段自动为我们传入的taeget设置了名为propertyName的属性值(使用setter和getter方法)。
最后列一些Animator中定义的方法,或者查看官方文档
Public methods | |
---|---|
void | addListener(Animator.AnimatorListener listener) 添加动画监听 |
void | addPauseListener(Animator.AnimatorPauseListener listener) 添加动画暂停监听 |
void | cancel() 取消动画 |
Animator | clone() 返回一个当前动画的拷贝 |
void | end() 结束动画 |
abstract long | getDuration() 获取动画持续时间 |
TimeInterpolator | getInterpolator() 获取当前动画的插值器 |
ArrayList<Animator.AnimatorListener> | getListeners() 获取当前监听器列表 |
abstract long | getStartDelay() 获取动画开始前延迟时间 |
long | getTotalDuration() 获取当前动画的总时间,包括重复时间和延迟时间等 |
boolean | isPaused() 返回动画是否暂停 |
abstract boolean | isRunning() 返回当前动画是否正在执行 |
boolean | isStarted() 返回当前动画是否开始执行 |
void | pause() Pauses a running animation. |
void | removeAllListeners() 移除所有监听器 |
void | removeListener(Animator.AnimatorListener listener) 移除指定监听器 |
void | removePauseListener(Animator.AnimatorPauseListener listener) 移除暂停监听 |
void | resume() 将暂停动画继续执行 |
abstract Animator | setDuration(long duration) 设置动画持续时间 |
abstract void | setInterpolator(TimeInterpolator value) 设置插值器 |
abstract void | setStartDelay(long startDelay) 设置动画开始前延迟 |
void | setTarget(Object target) 设置执行动画对象 |
void | setupEndValues() 设置动画结束值 |
void | setupStartValues() 设置动画开始值 |
void | start() 开始此动画 |
这篇就先这样,关于属性动画的底层执行逻辑,讲道理我理解的还不够,等以后知识储备能足以理解这一块的时候再回来重写吧。老规矩,代码地址:github
欢迎来我的博客讨论相关问题~