在上一篇Android动画基础之补间动画与逐帧动画 ,我们复习了Android的基础动画Tweened Animation、Frame Animation,同时指出他们的缺陷,改变是View的显示效果而不是View本身的属性,还有我们不多不少会看多人家的APP有一些很酷炫的动画效果,但是我们Android本身的基础动画是用硬编码方式完成的,功能很有限,扩展性很差,无法满足的现今的产品需求。因为我们今次的主角要出现了,Property Animation属性动画。
属性动画(Property Animation) 属性动画是在Android3.0中引进的,它更改的是对象的实际属性,在基础动画中改变的是View的绘制效果,真正的View的属性是没有改变的,而属性动画,改变的是对象的实际属性,能编写各种满足我们需求的动画。
Property Animation相关类:
ValueAnimator:包括Property Animation动画的所有核心功能,如动画时间、开始、结束属性值。
ObjectAnimator:继承于ValueAnimator,要指定一个对象及该对象的一个属性,当属性值计算完成时自动设置为改该对象的相对属性。实际应用中一般会用ObjectAnimator来改变某一对象的某一属性。
AnimatorSet:提供了一个把多个动画组合成一个组合的机制。
AnimatorInflater:用于加载属性动画的xml文件
TypeEvalutors:类型估值,主要用于设置动画操作属性的值
Android提供了以下几个evalutor:
IntEvaluator:属性的值类型为int;
FloatEvaluator:属性的值类型为float;
ArgbEvaluator:属性的值类型为十六进制颜色值;
- TimeInterplator:时间差值,定义了动画属性值变化的方式,在Property Animation中是TimeInterplator,在View Animation中是Interplator,这两个是一样的,在3.0之前只有Interplator,3.0之后实现代码转移至了 TimeInterplator。Interplator继承自TimeInterplator,内部没有任何其他代码。
ValueAnimator
- 调用ValueAnimator提供的静态方法实例化ValueAnimator对象,如ofArgb(int… values)、ofFloat(float… values)等,并设置目标属性的属性名、初始值、结束值等;
- 调用ValueAnimator.addUpdateListener(AnimatorUpdateListener listener)为ValueAnimator对象设置属性变化的监听器;
- 创建自定义的Interpolator,调用setInterpolator(TimeInterpolator value)为ValueAniamtor设置自定义的Interpolator;
- 创建自定义的TypeEvaluator,调用setEvaluator(TypeEvaluator value)为ValueAnimator设置自定义的TypeEvaluator;
- 在AnimatorUpdateListener中的实现方法为目标对象的属性设置计算好的属性值;
- 设置动画的持续时间、是否重复及重复次数等属性;
- 对ValueAnimator设置目标对象并开始执行动画。
下面我们简单地使用一下ValueAnimator:
ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 100);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Log.i("onAnimationUpdate", "onAnimationUpdate: " + animation.getAnimatedValue());
}
});
valueAnimator.setDuration(200);
valueAnimator.start();
上面代码我们是用ofInt()方法,带的参数是0,100,然后通过用AnimatorUpdateListener设置动画监听,如下图看到动画的值在200毫秒内从0到100打印出来。
ObjectAnimator
我们接着学习一下ObjectAnimator这动画实现类的用法,首先ObjectAnimator继承ValueAnimator,那就说ObjectAnimator可以重写ValueAnimator父类提供的方法。在实际开发中,我们更多地使用ObjectAnimator来实现我们需要的动画效果。在之前我们说过ViewAnimation的缺点,所以Android3.0中为View增加了一些新属性以及对应的getter、setter方法。那我们来看一下这些新增的动画属性:
1.translationX和translationY:这两个属性控制着View的屏幕位置坐标变化量,以layout容器的左上角为坐标原点;
2.rotation、rotationX 和 rotationY:这三个属性控制着 2D 旋转角度(rotation属性)和围绕某枢轴点的 3D 旋转角度;
3.scaleX、scaleY:这两个属性控制着 View 围绕某枢轴点的 2D 缩放比例;
4.pivotX 和 pivotY: 这两个属性控制着枢轴点的位置,前述的旋转和缩放都是以此点为中心展开的,缺省的枢轴点是 View 对象的中心点;
5.x 和 y:这是指 View 在容器内的最终位置,等于 View 左上角相对于容器的坐标加上 translationX 和 translationY 后的值;
alpha:表示 View 的 alpha 透明度。缺省值为 1 (不透明),为 0 则表示完全透明(看不见);
然而用法跟ValueAnimator大同小异,我们通过例子来说明:
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 360f);
animator.setDuration(1000);
animator.start();
感觉是没区别啊,我们ObjectAnimator其实是对继承了View控件的属性setter、getter方法进行修改值的。ObjectAnimator可以在属性上进行操作,而ValueAnimator并没有在属性上做操作,ObjectAnimator对一些简单的动画使用起来比较方便,而ValueAnimator就比较灵活,之后我们会详细讲解。
组合动画AnimatorSet
组合动画,PropertyAnimation是用到AnimatorSet这个类,该类提供一个play()的方法,还有提供:
- after(Animator anim) 将现有动画插入到传入的动画之后执行
- after(long delay) 将现有动画延迟指定毫秒后执行
- before(Animator anim) 将现有动画插入到传入的动画之前执行
- with(Animator anim) 将现有动画和传入的动画同时执行
ObjectAnimator moveIn = ObjectAnimator.ofFloat(image, "translationX", -100f, 0f);
ObjectAnimator rotate = ObjectAnimator.ofFloat(image, "rotation", 0f, 180f);
ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(image, "alpha", 1f, 0f, 1f);
AnimatorSet animSet = new AnimatorSet();
animSet.play(rotate).with(fadeInOut).after(moveIn);
animSet.setDuration(2000);
animSet.start();
感觉比较基础的用法。
XML编写动画
用XML来编写描述我们需要的动画可能是我们最常用的一种做法,所以PropertyAnimation肯定也提供这种XML的方式来实现功能。在XML我们常用到的三个标签:
<animator>
对应代码中的ValueAnimator<objectAnimator>
对应代码中的ObjectAnimator<set>
对应代码中的AnimatorSet
标签是可以嵌套的。
标签的android:ordering属性规定了这个set中的动画的执行顺序。该属性值默认是together (default)。
首先要在res目录下面新建一个animator文件夹,然后我们的XML代码的实现如下:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="sequentially">
<objectAnimator
android:duration="2000"
android:propertyName="translationX"
android:valueFrom="-500"
android:valueTo="0"
android:valueType="floatType" />
<set android:ordering="together">
<objectAnimator
android:duration="3000"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360"
android:valueType="floatType" />
<set android:ordering="sequentially">
<objectAnimator
android:duration="1500"
android:propertyName="alpha"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType" />
<objectAnimator
android:duration="1500"
android:propertyName="alpha"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType" />
</set>
</set>
</set>
XML文件写好,那么我们用Java代码将对于的动画加载并启动。
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.anim_set);
animator.setTarget(image);
animator.start();
Animator监听器
在动画的绘制中,肯定少不了我们的动画监听事件来处理各种需求和逻辑,Animator类当中提供了一个addListener()方法:
mAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
可以看到,我们需要实现接口中的四个方法,onAnimationStart()方法会在动画开始的时候调用,onAnimationRepeat()方法会在动画重复执行的时候调用,onAnimationEnd()方法会在动画结束的时候调用,onAnimationCancel()方法会在动画被取消的时候调用。
但是有些时候我们可能只想要监听动画开始这一个事件,那么每次都要将四个接口全部实现一遍就显得非常繁琐。所以Android提供了一个适配器类,叫作AnimatorListenerAdapter,使用这个类就可以解决掉实现接口繁琐的问题了,如下所示:
mAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
}
});
好的,通过本篇文章的学习,我想大家已经对属性动画的基本API用法已经有了一定的认识,并把最常用的一些功能都掌握好了。接下来下一篇我们继续深入学习PropertyAnimation。