本篇文章主要介绍属性动画,需要了解补间动画和帧动画相关知识的,建议阅读Android动画详解(上)。属性动画非常强大,运用也非常灵活,为了便于理解,本文首先从类的角度介绍了属性动画的继承关系,然后针对一些重点类介绍了其内的主要方法,最后通过demo的方式对属性的动画的常见用法进行了演示。
类继承关系
属性动画存放在android.animation包下,主要的类继承关系如下:
主要方法
Animator是一个抽象类,其内提供了一些公共方法。需要注意的是,一些方法是需要子类去重写的,比如getInterpolator()这个方法目前直接返回null,子类需要根据实际情况返回Interpolator。
ValueAnimator是属性动画中非常常用的一个类,除了实现或重写了父类的上述方法外,其还增加了一些新的功能,如常用的估值器的设置。
AnimatorSet主要用来控制动画组合的播放顺序及方式,特别是其的Builder,功能强大,使用方便。
常见用法
属性动画的用法非常灵活,首先从简单的平移动画开始入手,效果如如下:
代码比较简单,老规矩,介绍xml和Java两种实现方式:
xml实现方式:
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="translationX"
android:duration="2000"
android:valueFrom="0"
android:valueTo="500"
android:repeatCount="1"
android:repeatMode= "reverse"
/>
Java中调用代码:
ObjectAnimator objectAnimator= (ObjectAnimator)AnimatorInflater.loadAnimator(this,R.animator.propertyanimation);
objectAnimator.setTarget(mAnimationBtn0);
objectAnimator.start();
需要注意的是xml代码是放在res的animator目录下,另外注意repeatCount的值和repeatMode选项。
Java实现方式:
ObjectAnimator translationXAnimation = ObjectAnimator.ofFloat(mAnimationBtn0, "translationX", 0, 500);
translationXAnimation.setDuration(2000);
translationXAnimation.setRepeatCount(1);
translationXAnimation.setRepeatMode(ValueAnimator.REVERSE);
translationXAnimation.start();
上述Java代码之所以能够实现平移效果是因为mAnimationBtn0这个Target属于View包含translationX对应的get/set方法。至于为啥是ofFloat而不是ofInt,是因为其get/set方法对应的方法参数为float类型,它们是相互关联的。
旋转、缩放等动画与平移动画类似,就不再介绍了。
假如我们需要改变一个View的宽度,但是View里面却没有对应的get/set该如何实现呢?方案很多,为了对比学习,挑选了三种典型的方案,效果图如下:
从图中可以看到红、蓝、绿三个View的变化效果一致,但是正如其显示的内容一样,使用了不同的方式,分别为ObjectAnimator.ofInt、ValueAnimator.ofInt 、ValueAnimator.ofObject。
ObjectAnimator.ofInt 方式
该方式是处理这种没有对应set/get方法却想使用属性动画情况的常用的方式,主要思路是利用装饰者模式,对现有target进行装饰,在装饰类里提供set/get操作,完成相关属性的设置。实现步骤如下:
步骤一:创建装饰类
public class WidthWrapper {
private View mTargetView;
WidthWrapper(View view) {
mTargetView = view;
}
public int getWidth(){
return mTargetView.getLayoutParams().width;
}
public void setWidth(int width) {
mTargetView.getLayoutParams().width = width;
mTargetView.requestLayout();
}
}
<