前言
属性动画是Android 3.0(API 11)
新加入的动画框架,属性动画弥补了视图动画的很多短板,因此已经成为大多数动画场景的首选框架。
目录

1. 属性动画出现的原因
在属性动画出现以前,Android主要有两种动画,帧动画(Frame Animation
)和补间动画(Tween Animation
),这两种动画统称为视图动画。帧动画是通过逐帧播放图片来实现动画效果,补间动画虽然提供了旋转、缩放、位移、透明度的动画效果,却有不可忽视的3大缺陷:
- 作用对象有限,只能作用于View及其子类
- 动画种类有限,只有旋转、缩放、位移、透明度4种动画
- 只是改变了View的显示效果,没有真正改变View的属性。例如:对
View作位移的补间动画后,View虽然显示改变,但是响应区域却还在原来的位置,这在很多应用场景下是不可行的。
因此,为了弥补视图动画的不足,属性动画就应运而生了。
2. 属性动画概述
2.1 原理
属性动画通过在预设的规则下不断地改变值,并将值设置给作用对象的属性,从而达到动画效果。这个规则可以由我们定制,其中有两个重要的工具,可以帮助我们定制值的变化规则,一个是插值器(Interpolator
),一个是估值器(TypeEvaluator
)
2.2 插值器
插值器定义了动画的变化率,能帮助我们实现非线性改变的动画。Android提供了几种插值器,如加速变化的AccelerateInterpolator,先加速后减速的AccelerateDecelerateInterpolator等等,感兴趣的朋友可以自行百度查看。如果系统提供的插值器不能满足我们的要求,我们还可以自定义插值器(通过下面的方式)
/**
* 自定义插值器
* 实现TimeInterpolator接口
*
*/
class MyInterpolator implements TimeInterpolator{
//实现getInterpolation方法
//此方法的参数input可理解为动画的进度,值的区间是在[0,1],在此区间里随着时间均匀地改变
//返回值是内插值,从广义上理解是一个时间因子,体现了动画在时间上的变化因素;从狭义上可理解为动画改变的百分比
@Override
public float getInterpolation(float input) {
return 0;
}
}
2.3 估值器
估值器的作用是根据开始值、结束值、开始结束之间的一个比例来计算出最终的值。在属性动画上则是计算出动画对应的最终的属性值。系统默认提供了3种估值器
- IntEvaluator整型估值器,值的类型为整型
- FloatEvaluator浮点型估值器,值的类型为浮点型
- ArgbEvaluator,值的类型为ARGB值,可以用来计算颜色值
如果系统提供的估值器不能满足我们的要求,我们还可以自定义估值器
/**
* 自定义估值器
* 实现TypeEvaluator接口
*/
class MyEvaluator implements TypeEvaluator<T>{
/**
*
* @param fraction 开始过渡到结束之间的一个比例
* @param startValue 开始值
* @param endValue 结束值
* @return 开始过渡到结束的具体值
*/
@Override
public T evaluate(float fraction, T startValue, T endValue) {
return null;
}
}
3. 属性动画的使用
属性动画主要通过两个类来使用,ValueAnimator和ObjectAnimator,这两个的区别主要是ValueAnimator只是计算值,赋值给对象属性需要我们手动监听值的变化来进行;ObjectAnimator则对赋值属性这一步封装进了内部,也就是自动赋值。
3.1 ValueAnimator
3.1.1 创建ValueAnimator
创建ValueAnimator可以在代码里面创建、设置,也可以在xml里面创建、设置
- xml创建
在res
目录里创建animator
目录,之后创建Animator resources file
,ValueAnimator在xml文件的根结点是animator,例如:
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:valueFrom="30"
android:valueTo="60"
android:duration="2000"
android:valueType="intType" //选择值的类型
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:repeatMode="reverse"
android:repeatCount="1">
</animator>
之后直接在代码里面加载刚才的资源文件就可以了
ValueAnimator valueAnimator= (ValueAnimator) AnimatorInflater.loadAnimator(this,R.animator.textsize_animator);
- 代码里创建
虽然ValueAnimator提供了公共的无参的构造方法,但是官方建议我们使用其工厂方法来创建ValueAnimator
(1)ValueAnimator.ofInt(int... values)
使用这种方式创建ValueAnimator,值的类型是int,会默认使用整形估值器。
(2)ValueAnimator.ofFloat(float... values)
对应值的类型是float,会默认使用浮点型估值器
(3)ValueAnimator.ofArgb(int... values)
对应值的类型是代表颜色的32位的int,会默认使用ArgbEvaluator估值器
(4)ValueAnimator.ofObject(TypeEvaluator evaluator,Object... values)
对应值的类型是Object,这种方式需要显式传入估值器,因为对于Object类型没有系统提供的估值器,也不可能提供估值器,因为对于不同的对象其计算方式不同
3.1.2 设置ValueAnimator
ValueAnimator提供了方法设置其动画的相关的属性,具体如下
valueAnimator.setDuration(2000);//设置动画持续时间,以毫秒为单位
valueAnimator.setInterpolator(new DecelerateInterpolator());//设置插值器
valueAnimator.setRepeatMode(ValueAnimator.REVERSE);//设置动画重复模式,RESTART表示动画正序重复,REVERSE代表倒序重复
valueAnimator.setRepeatCount(1);//设置重复次数,也就是动画播放次数=RepeatCount+1,ValueAnimator.INFINITE表示无限重复
valueAnimator.setStartDelay(1000);//设置动画延迟播放的时间
3.1.3 监听动画值
ValueAnimator提供了回调以监听动画值,我们可以在此回调中拿到属性值并手动赋值给对象属性,从而达到效果,需要注意的是,对象是View的时候,有时需要我们在赋值属性后调用View.invalidate()或者View.requestLayout()方法来刷新界面实现视觉效果
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {//动画值更新时的监听器
@Override
public void onAnimationUpdate(ValueAnimator animation) {//动画更新时会回调此方法
Float value= (Float) animation.getAnimatedValue();//拿到更新后动画值
tvAnimator.setTextSize(value);//手动将动画值赋值给对象
}
});
3.2 ObjectAnimator
ObjectAnimator利用反射调用对象属性的set方法从而自动赋值给对象属性完成动画,也就是说ObjectAnimator作用的对象必须提供该属性的set方法(如果没有提供初始值,还必须提供get方法)需要注意的是,set和get方法名必须满足如下规则
set/get+属性名(属性名头字母大写)
3.2.1 创建ObjectAnimator
- xml创建
在res/animator
目录下创建animator的xml文件,根结点为objectAnimator
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:valueType="floatType"
android:valueTo="200.0"
android:valueFrom="100.0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:propertyName="width"
/>
在代码里加载xml创建的ObjectAnimator并设置作用对象
ObjectAnimator objectAnimator= (ObjectAnimator) AnimatorInflater.loadAnimator(this,R.animator.test);//加载xml中的动画
objectAnimator.setTarget(tvAnimator);//设置作用对象
- 代码里创建
和ValueAnimator的方式差不多,这里以ofInt为例说明创建方式,其他的可以类推。
/*
1. 参数解释
target:ObjectAnimator作用的对象
propertyName:属性名
values:过渡值(开始值、结束值)
*/
ObjectAnimator objectAnimator=ObjectAnimator.ofInt(Object target,String propertyName,int... values);
3.2.2 设置ObjectAnimator
同ValueAnimator设置方式一样,不再赘述。
3.3 AnimatorSet(组合动画)
AnimatorSet用于把很多动画按照一定顺序组合起来播放,AnimatorSet采用了构造器模式来组合动画
public Builder play(Animator anim) {
if (anim != null) {
return new Builder(anim);
}
return null;
}
//play函数会生成构造器并将该动画加入到播放队列中
play函数是AnimatorSet中唯一可以创建构造器的函数,此外构造器还提供了多种方法组合动画,这些方法都是以play函数传入的Animator作为基准来构建播放顺序的,例如:
//将animator1和animator2一起播放
animatorSet.play(animator1).with(animator2);
//将animator1插入animator2之后播放
animatorSet.play(animator1).after(animator2);
//将animator1插入animator2之前播放
animatorSet.play(animator1).before(animator2);
AnimatorSet本身还提供了两个方法来添加动画,
public void playSequentially(Animator... items)//一个接一个地先后播放动画组,前面的动画先播放
public void playTogether(Animator... items)//同时播放动画组
这两个方法本质上也是采用了构造器的after、before和with方法来构建动画的播放顺序。
3.4 监听动画
Animator类允许对动画开始、结束、取消、重复和暂停等时刻进行监听
animator.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) {
}
});
animator.addPauseListener(new Animator.AnimatorPauseListener() {
@Override
public void onAnimationPause(Animator animation) {
}
@Override
public void onAnimationResume(Animator animation) {
}
});
如果只想监听其中的几个方法,可以采用AnimatorListenerAdapter
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
}
});
animator.addPauseListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationPause(Animator animation) {
}
});
网友评论