属性动画(property animation)是在 API11 引入的新特性,它相比于补间动画有如下优势:
本篇文章介绍的是属性动画的简单使用,结构如下:
ValueAnimator
是属性动画中最为核心的一个类,属性动画之所以叫做属性动画是因为它改变的是对象的属性值,所以属性动画的运行机制就是通过不断地对值进行修改来达到动画的效果。
而ValueAnimator
正是用于做这类计算的,它接收动画的开始值和结束值,然后利用内部的计时引擎不断地修改值,从初始值过渡到结束值。它有如下3个比较重要的方法用于创建ValueAnimator
对象:
方法 | 描述 |
---|---|
ValueAnimator.ofInt(int… values) | 将初始值以整型数值的形式过渡到结束值 |
ValueAnimator.ofFloat(float… values) | 将初始值以浮点型数值的形式过度到结束值 |
ValueAnimator.ofObject(TypeEvaluator evaluator, Object… values) | 将初始值以对象的形式过渡到结束值 |
在本部分我们会先介绍ofInt
和ofFloat
,ofObject
在估值器部分进行介绍,接下来我们看到ValueAnimator
中的常用方法:
方法 | 描述 |
---|---|
setDuration | 设置动画时长,单位为ms |
setStartDelay | 设置开始的延迟时间,单位为ms |
setRepeatCount | 设置重复次数,默认为0。取值为INFINITE表示无限重读 |
setRepeatMode | 设置重复模式,有两种取值:RESTART和REVERSE |
setEvaluator | 设置估值器 |
addUpdateListener | 添加值更新监听器,每当值更新时都会回调此方法 |
start | 开启动画 |
pause | 暂停动画 |
cancel | 关闭动画 |
接下来通过一个简单的例子来展示ValueAnimator
的使用:
ValueAnimator anim = ValueAnimator.ofFloat(0.0f, 100.0f);
anim.setDuration(500);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Log.d(TAG, "current value is " + animation.getAnimatedValue());
}
});
anim.start();
输出结果:
D/MainActivity: current value is 0.0
D/MainActivity: current value is 9.549156
D/MainActivity: current value is 74.909256
D/MainActivity: current value is 83.06559
D/MainActivity: current value is 86.875656
D/MainActivity: current value is 90.078354
D/MainActivity: current value is 93.037094
D/MainActivity: current value is 95.5053
D/MainActivity: current value is 97.35491
D/MainActivity: current value is 98.795845
D/MainActivity: current value is 99.680565
D/MainActivity: current value is 99.996056
D/MainActivity: current value is 100.0
本例中我们采用ofFloat
来初始化ValueAnimator
,然后将初始值和结束值设置为0和100,时长为500ms。添加监听的原因是我们没有将改值应用与任何View上,无法直观看到变化,所以通过打印Log的方式查看值的变化。如果我们想要采用整型值,如下所示:
ValueAnimator anim = ValueAnimator.ofInt(0, 100);
anim.setDuration(500);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Log.d(TAG, "current value is " + animation.getAnimatedValue());
}
});
anim.start();
只需改变第一行代码,我们的Log中打印出来的就全为整型值了。以上就是关于ValueAnimator
的简单使用,接下来我们看到ObjectAnimator
的使用。
ObjectAnimator
是ValueAnimator
的子类,相比于ValueAnimator
只能对值进行过渡,ObjectAnimator
则可以直接对任意对象的属性值进行动画操作,所以在平常开发中我们使用的更多的是ObjectAnimator
。而它创建对象的方式和 ValueAnimator
非常类似,提供了下列三个方法:
public static ObjectAnimator ofInt(Object target, String propertyName, int... values)
参数 | 描述 |
---|---|
target | 属性动画作用的对象,例如一个文本或者一个按钮 |
propertyName | 动画所作用的属性 |
values | 动画的过渡值,一般会在这里设置初始值和结束值,值类型为int |
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)
ofFloat
方法的使用和ofInt
方法类似,唯一的区别为values
的类型不同,ofFloat
方法采用的是float类型。
public static ObjectAnimator ofObject(Object target, String propertyName,
TypeEvaluator evaluator, Object... values)
参数 | 描述 |
---|---|
target | 属性动画作用的对象,例如一个文本或者一个按钮 |
propertyName | 动画所作用的属性 |
evaluator | 自定义的估值器 |
values | 动画的过渡值,一般会在这里设置初始值和结束值 |
ofObject
方法我们同样留待后面介绍估值器的时候再做介绍。下面我们以改变一个按钮的透明度为例,看下它的使用:
ObjectAnimator anim = ObjectAnimator.ofFloat(mButton, "alpha", 1.0f, 0.0f, 1.0f);
anim.setDuration(3000);
anim.start();
而其它诸如修改缩放比例的代码则可以如下所示:
ObjectAnimator anim = ObjectAnimator.ofFloat(mButton, "scaleX", 1.0f, 1.5f, 1.0f);
anim.setDuration(1000);
anim.start();
总体而言使用起来非常简单,接下来我们看到下一个:AnimatorSet
。
AnimatorSet即动画集合,它有两种使用方式:XML形式和Java代码的形式,首先看到XML形式的使用。
在属性动画的XML形式中,有下面几个标签可供选择:
标签 | 对应的类 |
---|---|
AnimatorSet | |
ValueAnimator | |
ObjectAnimator |
下面是各个标签所对应的属性名称及其描述。
属性 | 描述 |
---|---|
fillAfter | 动画播放结束后是否固定,默认为true |
interpolator | 插值器设置,默认为加减速插值器 |
repeatMode | 重复模式设置,课选择值有restart和reverse两种 |
repeatCount | 重复次数,默认为0 |
startOffset | 动画开启后的延时时间 |
startTime | 设置开始动画的时刻 |
属性 | 描述 |
---|---|
duration | 动画的持续时长,取值为int型数值,单位为毫秒 |
interpolator | 动画的插值器设置,默认为加速减速插值器 |
repeatCount | 重复次数,默认为0,取值为int型整数,代表重复次数 |
repeatMode | 重复模式,有restart和reverse两种取值,reverse表示动画正反轮流执行,restart表示一直从头开始执行 |
startOffset | 动画开始的延迟时间,取值为int型数值,单位为毫秒 |
valueFrom | 动画的初始值,取值可以为int型、float型或颜色值,取值类型受valueType属性影响 |
valueTo | 动画的结束值,取值可以为int型、float型或颜色值,取值类型受valueType属性影响 |
valueType | value的取值类型,可以取intType或者floatType,如果值类型为颜色值,那么无需定义此属性 |
objectAnimator标签的设置与animator的设置十分相似,animator标签可用的属性objectAnimator标签均可以用,下面只列举出部分objectAnimator特有的属性:
属性 | 描述 |
---|---|
propertyName | 表示属性动画作用对象的属性的名称 |
接下来通过一个例子来展示XML形式的使用:
// res/animator/anim_demo.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:propertyName="alpha"
android:valueType="floatType"
android:valueFrom="1.0"
android:valueTo="0.5"/>
<objectAnimator
android:propertyName="scaleX"
android:valueType="floatType"
android:valueFrom="1.0f"
android:valueTo="1.5f"/>
set>
在Java代码中,使用如下代码:
AnimatorSet animationSet = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.anim_demo);
animationSet.setTarget(mButton);
animationSet.start();
通过这种形式,我们就实现了在1s内同时改变按钮的透明度和x轴的伸缩的动画,效果如下所示:
以上就是关于AnimatorSet
在XML形式下的使用,下面介绍Java代码形式的使用,这是一种更加推荐的用法。
在Java代码中,我们只需要用到AnimatorSet类即可,下面我们先来介绍下这个类的常用 API:
方法 | 描述 |
---|---|
setTarget | 设置动画的作用对象,例如一个按钮 |
start | 开启动画的方法 |
cancel | 取消动画的方法 |
pause | 暂停动画的方法 |
play | 这个方法会返回一个Builder对象,传入的值为ValueAnimator对象或者ObjectAnimator对象,Builder类用于协助构造动画集合 |
with | 将现有动画和传入的动画同时执行 |
before | 将现有动画插入到传入的动画之前执行 |
after(Animator anim) | 将现有动画插入到传入的动画之后执行 |
after(long delayTime) | 将现有动画延迟指定毫秒后执行 |
接下来我们就通过一个实际的例子来展示它的使用。
ObjectAnimator alpha = ObjectAnimator.ofFloat(mButton, "alpha", 1.0f, 0.0f, 1.0f);
ObjectAnimator scaleX = ObjectAnimator.ofFloat(mButton, "scaleX", 1.0f, 1.5f, 1.0f);
ObjectAnimator rotate = ObjectAnimator.ofFloat(mButton, "rotationX", 0.0f, 360.0f);
AnimatorSet animationSet = new AnimatorSet();
// 在进行x轴缩放之前,先同时进行透明度和旋转动画。
animationSet.play(rotate).with(alpha).before(scaleX);
animationSet.setDuration(5000);
animationSet.start();
运行代码,效果如下所示:
可以发现按钮先进行旋转和透明度动画(这两个是同时进行的),然后再进行x轴的拉伸动画。结果与我们的预期是相符的。
为了让我们能够更加轻松地使用属性动画,Android官方还为我们提供了一个面向对象的属性动画操作方式。它的使用方式如下所示:
View.animate().xxx().xxx();
我们这里以一个按钮动画为例展示它的使用:
mButton.animate().scaleX(2.0f).alpha(0.0f).setDuration(2000).setInterpolator(new LinearInterpolator());
效果如下所示:
需要注意的是这种设置下的动画是同时进行的,并且动画会自动启动,无需调用start
方法。可以看到关于ViewPropertyAnimator的使用还是非常简单的,但我们只需要简单地对View中的一些常规属性进行动画操作时就可以考虑使用ViewPropertyAnimator。
属性动画提供了监听器用于监听动画的播放过程,主要有以下三个接口:AnimatorUpdateListener
、AnimatorListener
和AnimatorPauseListener
。
AnimatorUpdateListener
接口的定义如下:
public static interface AnimatorUpdateListener {
/**
* Notifies the occurrence of another frame of the animation.
*
* @param animation The animation which was repeated.
*/
void onAnimationUpdate(ValueAnimator animation);
}
可以看到这个接口中只有一个方法onAnimationUpdate
,它会在动画属性值被更新的时候回调,也就是说在动画每播放一帧的时候它就会被回调一次。该监听通过addUpdateListener
方法添加该监听事件。
AnimatorListener
接口的定义如下:
public static interface AnimatorListener {
void onAnimationStart(Animator animation);
void onAnimationEnd(Animator animation);
void onAnimationCancel(Animator animation);
void onAnimationRepeat(Animator animation);
}
AnimatorListener
接口则定义了四个方法,这四个方法会分别在动画开始、结束、取消、重播时被回调,我们可以通过addListener
方法来添加该监听事件。
相比上面两个接口,AnimatorPauseListener
的使用频率偏低,该接口定义了以下两个方法:
public static interface AnimatorPauseListener {
/**
* Notifies that the animation was paused.
*
* @param animation The animaton being paused.
* @see #pause()
*/
void onAnimationPause(Animator animation);
/**
* Notifies that the animation was resumed, after being
* previously paused.
*
* @param animation The animation being resumed.
* @see #resume()
*/
void onAnimationResume(Animator animation);
}
这两个方法分别在动画暂停和暂停恢复时进行回调,可以通过addPauseListener
方法添加该监听事件。
《Android开发艺术探索》
Android属性动画完全解析(上),初识属性动画的基本用法
希望这篇文章对你有所帮助~