在日常的Android开发中,我们可能经常会使用到动画,但是Android有哪些动画,它们有什么区别,我们也需要去了解。下面就对Android中常用的动画做一下总结。

前面一篇文章已经总结了传统动画,如果需要了解,可以点击下面链接。
Android 动画(一)Animation

或者想了解下插值器和估值器,可以点击下面链接。
Android 动画(三)插值器和估值器

属性动画,是通过操作对象属性的动画。因此,所有补间动画的内容,都可以通过属性动画实现。

属性动画核心原理

在上面实现属性动画的时候,我们使用到了ObjectAnimator这个类,这个类继承自ValueAnimator,而ValueAnimator则继承自Animator
使用这个类可以对任意对象的任意属性进行动画操作。而ValueAnimator是整个属性动画机制当中最核心的一个类。

属性动画的运行机制是通过不断地对值进行操作来实现的,而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。
它的内部使用一种时间循环的机制来计算值与值之间的动画过渡,我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,那么ValueAnimator就会完成从初始值平滑地过渡的效果。
除此之外,ValueAnimator还负责管理动画的播放次数、播放模式、以及对动画设置监听器等。

但是,动画是怎样平滑过渡的呢?实际上是由TypeEvaluatorTimeInterpolator决定的:

TypeEvaluator决定了动画如何从初始值过渡到结束值。
TimeInterpolator 决定了动画从初始值过渡到结束值每一秒具体的属性值。

属性动画实现传统动画

1
2
3
4
5
6
7
8
9
10
11
12
13
private void RotateAnimation() {
ObjectAnimator anim = ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
anim.setDuration(1000);
anim.start();
}

private void AlpahAnimation() {
ObjectAnimator anim = ObjectAnimator.ofFloat(myView, "alpha", 1.0f, 0.8f, 0.6f, 0.4f, 0.2f, 0.0f);
anim.setRepeatCount(-1);
anim.setRepeatMode(ObjectAnimator.REVERSE);
anim.setDuration(2000);
anim.start();
}

当然属性动画也可以组合使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(myView, "alpha", 1.0f, 0.5f, 0.8f, 1.0f);
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(myView, "scaleX", 0.0f, 1.0f);
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(myView, "scaleY", 0.0f, 2.0f);
ObjectAnimator rotateAnim = ObjectAnimator.ofFloat(myView, "rotation", 0, 360);
ObjectAnimator transXAnim = ObjectAnimator.ofFloat(myView, "translationX", 100, 400);
ObjectAnimator transYAnim = ObjectAnimator.ofFloat(myView, "tranlsationY", 100, 750);
AnimatorSet set = new AnimatorSet();
// 同时进行
set.playTogether(alphaAnim, scaleXAnim, scaleYAnim, rotateAnim, transXAnim, transYAnim);
// 按时序进行
//set.playSequentially(alphaAnim, scaleXAnim, scaleYAnim, rotateAnim, transXAnim, transYAnim);
set.setDuration(3000);
set.start();

animate()的原理

1
2
3
4
5
6
ViewPropertyAnimator animator = tvTodayRank.animate();
animator.alpha(1f)
.rotation(360f)
.scaleX(25f)
.scaleXBy(23f)
.start();

看一下调用start()的源码,调用start()后执行:

1
2
3
4
5
6
7
8
9
10
11
/**
* Starts the currently pending property animations immediately. Calling <code>start()</code>
* is optional because all animations start automatically at the next opportunity. However,
* if the animations are needed to start immediately and synchronously (not at the time when
* the next event is processed by the hierarchy, which is when the animations would begin
* otherwise), then this method can be used.
*/
public void start() {
mView.removeCallbacks(mAnimationStarter);
startAnimation();
}

startAnimation():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* Starts the underlying Animator for a set of properties. We use a single animator that
* simply runs from 0 to 1, and then use that fractional value to set each property
* value accordingly.
*/
private void startAnimation() {
if (mRTBackend != null && mRTBackend.startAnimation(this)) {
return;
}
mView.setHasTransientState(true);
ValueAnimator animator = ValueAnimator.ofFloat(1.0f);

// ... 省了部分代码

animator.start();
}

当调用start()方法后,还是会转化为Animator执行;