Android中的动画分为三种:View动画、帧动画、属性动画
属性动画
一、简介
属性动画是API 11 新加入的动画特性,对于API 11之前的版本可以使用开源的动画库nineoldandroids来兼容之前的版本。Google引入属性动画是为了解决view动画的一些缺陷。
view动画的缺陷:
1、只能够作用在视图View上,即只可以对一个Button、TextView、LinearLayout或者其它继承自View的组件进行动画操作,但无法对非View的对象进行动画操作。
2、只是改变了View的视觉效果,而不会真正去改变View的属性。
3、效果单一,只能实现平移、旋转、缩放 & 透明度这些简单的动画需求。
属性动画的作用对象是任意的Java对象。可实现各种动画效果。
属性动画的工作原理:在一定的时间内,通过不断的对值进行改变,并将该值赋值给对象的属性,从而实现动画效果。
实现属性动画涉及到三个类ObjectAnimator、ValueAnimator、AnimatorSet
二、ObjectAnimator
直接对对象的属性值进行改变操作,从而实现动画效果。底层的动画实现机制是基于ValueAnimator类。
具体使用,Java代码和xml:
1、Java代码
//创建动画实例
ObjectAnimator animator = ObjectAnimator.ofFloat(Object object, String property, float ....values);
// 设置动画运行的时长
anim.setDuration(500);
// 设置动画延迟播放时间
anim.setStartDelay(500);
// 设置动画重复播放次数
anim.setRepeatCount(0);
//设置重复播放动画模式RESTART(默认)正序重放/REVERSE:倒序回放
anim.setRepeatMode(ValueAnimator.RESTART);
// 启动动画
animator.start();
2、在XML 代码中设置
<1> 首先在res目录下创建animator文件夹
<2> 在res/animator 的文件夹里创建动画效果test_animator.xml文件
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:valueFrom="1" // 初始值
android:valueTo="0" // 结束值
android:valueType="floatType" // 变化值类型 :floatType & intType
android:propertyName="alpha" // 对象变化的属性名称/>
<3> 启动动画
// 载入XML动画
Animator animator = AnimatorInflater.loadAnimator(context, R.animator.view_animation);
// 设置动画对象
animator.setTarget(view);
// 启动动画
animator.start();
3、基本属性:
Alpha 控制View的透明度 float
TranslationX 控制X方向的位移 float
TranslationY 控制Y方向的位移 float
ScaleX 控制X方向的缩放倍数 float
ScaleY 控制Y方向的缩放倍数 float
Rotation 控制以屏幕方向为轴的旋转度数 float
RotationX 控制以X轴为轴的旋转度数 float
RotationY 控制以Y轴为轴的旋转度数 float
4、任意属性:
属性动画要求作用的对象提供该属性的get和set方法,如果想让动画生效,需要满足:
1、该对象属性必须提供set方法,属性动画需要使用set方法来设置属性值
2、如果没有设置动画的初始值的话,还需要提供get方法来获取初始值
3、 getff(如果需要)和set方法必须是相同的类型
如果该属性没有set、get方法的话或者是set方法中没有对属性进行相应的操作,比如Button中的setWidth()方法,该方法 是TextView中的方法,是为了设置TextView的最大最小宽度的,而没有设置Button的宽度,所以通过setWidth无法改变Button的宽度,此时对width做属性动画就没有效果。
对于这个问题,官方给了三种解决方法:
1、给对象添加get、set方法,如果有权限的话(很多时候没权限去这么做,当然在自定义view中可以使用此方法)
2、使用一个类来包装原始对象。间接为对象的属性提供get和set方法
3、利用ValueAnimator
下面简单介绍一下第二种方法的使用:
<1> 创建一个类,比如ViewWrapper
public class ViewWrapper{
priavte View mTarget;
public ViewWrapper(View target){
mTarget = target;
}
public int getWidth(){
return mTarget.getLayoutParams.width;
}
public void setWidth(int width){
mTarget.getLayoutParams.width = width;
mTarget.requestLayout();
}
}
<2> 实例化ViewWrapper类,开始动画
ViewWrapper wrapper = new ViewWrapper(button);
//让Button的宽度在5秒内变化到500
ObjectAnimator.ofInt(wrapper,"width",500).setDuration(5000).start();
三、VauleAnimator
ValueAnimator是整个属性动画机制当中最核心的一个类,属性动画的运行机制是通过不断地对值进行操作来实现的,而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。它的内部使用一种时间循环的机制来计算值与值之间的动画过渡,只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。 除此之外,ValueAnimator还负责管理动画的播放次数、播放模式、以及对动画设置监听器等。
使用:
获取ValueAnimator实例可以通过ofInt(), ofFloat(), or ofObject()来获取。比如:
ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(1000);
//将改变的值手动赋值给对象的属性值:通过动画的更新监听器
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// 获得改变后的值
int currentValue = (Integer) animation.getAnimatedValue();
//将改变后的值赋给对象的属性值,下面会详细说明
...
//刷新视图,即重新绘制,从而实现动画效果
...
}
});
animation.start();
ValueAnimator.ofObject()
将初始值 以对象的形式 过渡到结束值 即通过操作 对象 实现动画效果。在使用ValueAnimator.ofObject()的时候需要使用到估值器(TypeEvaluator)。
myObject object1 = new myObject();
myObject object2 = new myObject();
ValueAnimator anim = ValueAnimator.ofObject(new myObjectEvaluator(), object1, object2);
Interpolator 插值器
是一个接口,作用是设置属性值从初始值过渡到结束值的变化速率,比如匀速、加速 & 减速 等等。 实现非线性运动的动画效果。
Android系统内部内置了9种插值器:
加速 | @android:anim/accelerate_interpolator | AccelerateInterpolator |
---|---|---|
完成超出再回到结束位置 | @android:anim/overshoot_interpolator | OvershootInterpolator |
先加速再减速 | @android:anim/accelerate_decelerate_interpolator | AccelerateDecelerateInterpolator |
先退后再加速前进 | @android:anim/anticipate_interpolator | AnticipateInterpolator |
先退后再加速前进,超出终点后再回终点 | @android:anim/anticipate_overshoot_interpolator | AnticipateOvershootInterpolator |
最后阶段弹球效果 | @android:anim/bounce_interpolator | BounceInterpolator |
周期运动 | @android:anim/cycle_interpolator | CycleInterpolator |
减速 | @android:anim/decelerate_interpolator | DecelerateInterpolator |
匀速 | @android:anim/linear_interpolator | LinearInterpolator |
自定义插值器
自定义插值器需要实现 Interpolator接口 & 复写getInterpolation()方法。
public class CustomInterpolator implements Interpolator {
@Override
public float getInterpolation(float input) {
return (float) Math.sin((input) * Math.PI * 0.5F);
}
}
TypeEvaluator 估值器
接口。作用是设置属性值从初始值过渡到结束值的变化具体数值。
插值器(Interpolator)决定 值 的变化规律(匀速、加速blabla),即决定的是变化趋势;而接下来的具体变化数值则交给而估值器。
系统内置了3中估值器:
IntEvaluator: 针对整型属性
FloatEvaluator:针对浮点型属性
ArgbEvaluator: 针对Color属性
自定义估值器
自定义估值器需要实现 TypeEvaluator接口 & 复写evaluate()函数
// 实现TypeEvaluator接口
public class ObjectEvaluator implements TypeEvaluator{
// 复写evaluate()
// 在evaluate()里写入对象动画过渡的逻辑
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {
// 参数说明
// fraction:表示动画完成度(根据它来计算当前动画的值)
// startValue、endValue:动画的初始值和结束值
...
return value;
// 返回对象动画过渡的逻辑计算后的值
}
TimeInterpolator和TypeEvaluator是怎么协同工作的呢?
它们是实现非匀速动画的重要手段。属性动画是对属性做动画,属性要实现动画:
首先由TimeInterpolator(插值器)根据时间流逝的百分比计算出当前属性值改变的百分比,并将这个百分比返回,这个时候插值器的工作就完成了。比如插值器返回的值是0.5,很显然要的不是0.5,而是当前属性的值,即当前属性变成了什么值,这就需要估值器根据当前属性改变的百分比来计算改变后的属性值,根据这个属性值,就可以设置当前属性的值了。