- 按目前来说,Android的动画分为两大类,视图动画以及属性动画。由于属性动画更加灵活,目前主要使用属性动画。
- 属性动画使用
ValueAnimator
或ObjectAnimator
来实现单个动画,将多个动画可以组合成一组动画AnimatorSet
。 ValueAnimator
只对单个值进行持续变化,需要借助动画监听器监听这个变化中的值。以下为使用ValueAnimator
添加动画效果:
ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f);
animation.setDuration(1000);
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator updatedAnimation) {
// You can use the animated value in a property that uses the
// same type as the animation. In this case, you can use the
// float value in the translationX property.
float animatedValue = (float)updatedAnimation.getAnimatedValue();
textView.setTranslationX(animatedValue);
}
});
animation.start();
除了通过代码,还可以通过资源文件创建动画。属性动画的 XML 文件保存到res/animator/
目录中。这里的<animator>
标签对应的就是ValueAnimator
。
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:valueType="floatType"
android:valueFrom="0f"
android:valueTo="-100f" />
在资源文件中声明后,在代码中创建ValueAnimator
。
ValueAnimator xmlAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this, R.animator.animator);
xmlAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator updatedAnimation) {
float animatedValue = (float)updatedAnimation.getAnimatedValue();
textView.setTranslationX(animatedValue);
}
});
xmlAnimator.start();
这是ValueAnimator
的原型,继承于Animator
:
package android.animation;
public class ValueAnimator extends Animator implements AnimationHandler.AnimationFrameCallback {
……
}
ObjectAnimator
可以对目标对象的某个属性值进行持续变化。在大多数情况下,使用ObjectAnimator
相比ValueAnimator
可以极大地简化对目标对象的值添加动画效果这一过程。
ObjectAnimator animation = ObjectAnimator.ofFloat(textView, "translationX", 100f);
animation.setDuration(1000);
animation.start();
要使ObjectAnimator
正确更新属性,该属性必须要有setter方法。如果在ObjectAnimator
的一个工厂方法中仅为 values...
参数指定了一个值,则系统会假定它是动画的结束值。因此,要添加动画效果的对象属性还需要具有用于获取动画起始值的 getter 函数。
ObjectAnimator
同样可以在资源文件中创建:
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:valueTo="200"
android:valueType="floatType"
android:propertyName="y"
android:repeatCount="1"
android:repeatMode="reverse"/>
这是ObjectAnimator
的原型,它是ValueAnimator
的子类。
package android.animation;
public final class ObjectAnimator extends ValueAnimator {
……
}
- 使用
AnimatorSet
可以编排多个动画,对应的XML标签是<set>
。 Animator
类是上述3个类的抽象基类,在这个类中,定义了2个接口,分别是监听动画开始结束等的AnimatorListener
以及监听动画暂停恢复的AnimatorPauseListener
。
- 属性动画系统还提供了评估程序、插值器、关键帧等。
- 评估程序
TypeEvaluator
负责告知属性动画系统如何计算指定属性的值。常用的评估程序有IntEvaluator
、FloatEvaluator
、ArgbEvaluator
类,这些都实现了TypeEvaluator
接口。也可以自己实现TypeEvaluator
接口,如MyTypeEvaluator
类:
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
animation.setDuration(1000);
animation.start();
- 时间插值器
TimeInterpolator
指定了如何根据时间计算动画中的特定值。插值器的作用在于将时间分数转换为插值分数,评估程序再根据插值分数计算出结果。插值器都实现了TimeInterpolator
接口,默认的插值器是AccelerateDecelerateInterpolator
。 - 除了使用评估程序和插值器外,还可以指定关键帧
Keyframe
。关键帧直接指定几个时间分数对应的结果,每个关键帧还可以用自己的插值器控制动画在上一关键帧时间和此关键帧时间之间的时间间隔内的行为。这里需要借助PropertyValuesHolder
来生成ObjectAnimator
:
Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(.5f, 360f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation);
rotationAnim.setDuration(5000);
如果需要对单个View
对象的多个属性并行添加动画效果,可以使用多个ObjectAnimator
对象进行组合实现:
ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);
ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(animX, animY);
animSetXY.start();
也可以借助PropertyValuesHolder
合并成一个ObjectAnimator
:
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start();
或者使用ViewPropertyAnimator
,代码更加简洁,也更易读:
myView.animate().x(50f).y(100f);
ViewPropertyAnimator
内部借助ValueAnimator
实现动画效果,其并非继承于Animator
,且只能通过View
的animate
方法获得实例:
public ViewPropertyAnimator animate() {
if (mAnimator == null) {
mAnimator = new ViewPropertyAnimator(this);
}
return mAnimator;
}
参考:Android开发者 - 指南:视图动画,属性动画,属性动画与视图动画的区别,动画资源。