Android动画深入分析
Android的动画可以分为三种,View动画(补间动画),帧动画,属性动画。
View动画通过对场景里的对象不断做图像变换(平移,旋转,缩放,透明度),从而产生动画效果,它是一种渐进式动画,并且View动画支持自定义。
帧动画通过顺序播放一系列图像从而产生动画效果,可以简单理解为图片切换动画,很显然,如果图片过多过大就会导致OOM。
属性动画通过动态地改变对象的属性从而达到动画效果。
1. View动画的种类
View动画的四种变换效果对应着Animation的四个子类:TranslateAnimation、RotateAnimation、ScaleAnimation和AlphaAnimation。这四种动画既可以通过XML来定义,也可以通过代码来动态创建,对于View动画来说,建议采用XML来定义动画,这是因为XML格式的动画可读性更好。
View Animation:
基于View的渐变动画,它只改变了View的绘制效果,而实际属性值未变。比如动画移动一个按钮位置,但按钮点击的实际位置仍未改变。在代码中定义动画,可以参考AnimationSet类和Animation的子类;而如果使用XML,可以在res/anim/文件夹中定义XML文件。
要使用View动画,首先要创建动画的XML文件,这个文件的路径为:res/anim/filename.xml。View动画的描述文件是有固定的语法的。
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator=""
android:shareInterpolator="">
<translate
android:fromXDelta=""
android:toXDelta=""
android:fromYDelta=""
android:toYDelta=""/>
<rotate
android:fromDegrees=""
android:toDegrees=""
android:pivotX=""
android:pivotY=""/>
<scale
android:fromXScale=""
android:toXScale=""
android:fromYScale=""
android:toYScale=""
android:pivotX=""
android:pivotY=""/>
<alpha
android:fromAlpha=""
android:toAlpha=""/>
</set>
从上面的语法可以看出,View动画既可以是单个动画,也可以由一系列动画组成。
<set>标签表示动画集合,对应AnimationSet类,它可以包含若干个动画,并且它的内部也是可以嵌套其他动画集合的,它的两个属性的含义如下:
android:interpolator
表示动画集合所采用的插值器,插值器影响动画的速度,比如非匀速动画就需要通过插值器来控制动画的播放过程。这个属性可以不指定,默认为@android:anim/accelerate_decelerate_interpolator,即加速减速插值器。android:shareInterpolator
表示集合中的动画是否和集合共享同一个插值器,如果集合不指定插值器,那么子动画就需要单独指定所需的插值器或者使用默认值。
<translate>标签表示平移动画,对应TranslateAnimation类,它可以使一个View在水平和竖直方向完成平移的动画效果。
-
android:fromXDelta
表示X的起始值,比如0 -
android:toXDelta
表示X的结束值,比如100 -
android:fromYDelta
表示Y的起始值 -
android:toYDelta
表示Y的结束值
<?xml version="1.0" encoding="utf-8"?>
// 采用<translate /> 标签表示平移动画
<translate
xmlns:android="http://schemas.android.com/apk/res/android"
// 以下参数是4种动画效果的公共属性,即都有的属性
android:duration="3000" // 动画持续时间(ms),必须设置,动画才有效果
android:startOffset ="1000" // 动画延迟开始时间(ms)
android:fillBefore = “true” // 动画播放完后,视图是否会停留在动画开始的状态,默认为true
android:fillAfter = “false” // 动画播放完后,视图是否会停留在动画结束的状态,优先于fillBefore值,默认为false
android:fillEnabled= “true” // 是否应用fillBefore值,对fillAfter值无影响,默认为true
android:repeatMode= “restart” // 选择重复播放动画模式,restart代表正序重放,reverse代表倒序回放,默认为restart
android:repeatCount = “0” // 重放次数(所有动画的播放次数=重放次数+1),为infinite时无限重复
android:interpolator = @[package:]anim/interpolator_resource // 插值器,即影响动画的播放速度,下面会详细讲
// 以下参数是平移动画特有的属性
android:fromXDelta="0" // 视图在水平方向x 移动的起始值
android:toXDelta="500" // 视图在水平方向x 移动的结束值
android:fromYDelta="0" // 视图在竖直方向y 移动的起始值
android:toYDelta="500" // 视图在竖直方向y 移动的结束值
/>
// 在java中使用
btn1 = findViewById(R.id.btn1);
Animation translateAnimation = AnimationUtils.loadAnimation(this,R.anim.anim2);
btn1.startAnimation(translateAnimation);

<rotate>标签表示旋转动画,对应于RotateAnimation,它可以使View具有旋转的动画效果。
-
android:fromDegrees
旋转开始的角度,比如0 -
android:toDegrees
旋转结束的角度,比如180 -
android:pivotX
旋转的轴点的X坐标 -
android:pivotY
旋转的轴点的Y坐标
<?xml version="1.0" encoding="utf-8"?>
// 采用<rotate/> 标签表示是旋转动画
<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
// 以下参数是4种动画效果的公共属性,即都有的属性
android:duration="3000" // 动画持续时间(ms),必须设置,动画才有效果
android:startOffset ="1000" // 动画延迟开始时间(ms)
android:fillBefore = “true” // 动画播放完后,视图是否会停留在动画开始的状态,默认为true
android:fillAfter = “false” // 动画播放完后,视图是否会停留在动画结束的状态,优先于fillBefore值,默认为false
android:fillEnabled= “true” // 是否应用fillBefore值,对fillAfter值无影响,默认为true
android:repeatMode= “restart” // 选择重复播放动画模式,restart代表正序重放,reverse代表倒序回放,默认为restart|
android:repeatCount = “0” // 重放次数(所以动画的播放次数=重放次数+1),为infinite时无限重复
android:interpolator = @[package:]anim/interpolator_resource // 插值器,即影响动画的播放速度,下面会详细讲
// 以下参数是旋转动画特有的属性
android:duration="1000"
android:fromDegrees="0" // 动画开始时 视图的旋转角度(正数 = 顺时针,负数 = 逆时针)
android:toDegrees="270" // 动画结束时 视图的旋转角度(正数 = 顺时针,负数 = 逆时针)
android:pivotX="50%" // 旋转轴点的x坐标
android:pivotY="0" // 旋转轴点的y坐标
// 轴点 = 视图缩放的中心点
pivotX pivotY,可取值为数字,百分比,或者百分比p
设置为数字时(如50),轴点为View的左上角的原点在x方向和y方向加上50px的点。在Java代码里面设置这个参数的对应参数是Animation.ABSOLUTE。
设置为百分比时(如50%),轴点为View的左上角的原点在x方向加上自身宽度50%和y方向自身高度50%的点。在Java代码里面设置这个参数的对应参数是Animation.RELATIVE_TO_SELF。
设置为百分比p时(如50%p),轴点为View的左上角的原点在x方向加上父控件宽度50%和y方向父控件高度50%的点。在Java代码里面设置这个参数的对应参数是Animation.RELATIVE_TO_PARENT
两个50%表示动画从自身中间开始,具体如下图
/>

<scale>标签表示缩放动画,对应ScaleAnimation类,它可以使View具有放大或者缩小的动画效果。

-
android:fromXScale
水平方向的缩放起始值,比如0.5 -
android:toXScale
水平方向缩放的结束值,比如1.2 -
android:fromYScale
竖直方向缩放的起始值 -
android:toYScale
竖直方向缩放的结束值 -
android:pivotX
缩放的轴点的X坐标,它会影响缩放的效果 -
android:pivotY
缩放的轴点的Y坐标,它会影响缩放的效果
<alpha>标签表示透明度动画,对应AlphaAnimation,它可以改变View的透明度
-
android:fromAlpha
表示透明度的起始值,比如0.1 -
android:toAlpha
表示透明度的结束值,比如1
View动画还有一些常用的属性:
-
android:duration
动画的持续时间 -
android:fillAfter
动画结束以后,View是否停留在结束位置,true表示View停留在结束位置,false则不停留。
通过代码来应用动画
AlphaAnimation animation = new AlphaAnimation(0,1);
animation.setDuration(3000);
btn1.startAnimation(animation);
上面的代码,创建了一个透明度动画,将一个Button的透明度在3000ms内由0变为1,其他类型的View动画也可以通过代码来创建。
Animation animation = AnimationUtils.loadAnimation(this,R.anim.anim2);
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
Log.d("WM","start");
}
@Override
public void onAnimationEnd(Animation animation) {
Log.d("WM","end");
}
@Override
public void onAnimationRepeat(Animation animation) {
Log.d("WM","repeat");
}
});
btn1.startAnimation(animation);
Drawable Animation(帧动画):
加载一系列Drawable资源来创建动画,这种传统动画某种程度上就是创建不同图片序列,顺序播放,就像电影胶片。
在代码中定义动画帧,使用AnimationDrawable类;XML文件能更简单的组成动画帧,在res/drawable文件夹,使用<animation-list>采用<item>来定义不同帧。感觉只能设置的属性是动画间隔时间。
帧动画是顺序播放一组预先定义好的图片,类似于电影播放,不同于View动画,系统提供了另外一个类AnimationDrawable来使用帧动画。
<?xml version="1.0" encoding="utf-8"?>
<animation-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false"> //oneshot代表着是否只展示一遍,设置为false会不停的循环播放动画
<item android:drawable="@drawable/icon1" android:duration="150"/>
<item android:drawable="@drawable/icon2" android:duration="150"/>
<item android:drawable="@drawable/icon3" android:duration="150"/>
<item android:drawable="@drawable/icon4" android:duration="150"/>
<item android:drawable="@drawable/icon5" android:duration="150"/>
<item android:drawable="@drawable/icon6" android:duration="150"/>
</animation-list>
注意:图片和XML文件都放在Drawable文件夹下。
btn1.setBackgroundResource(R.drawable.anim_list);
AnimationDrawable drawable = (AnimationDrawable) btn1.getBackground();
drawable.start();
帧动画的使用比较简单,但是比较容易引起OOM,所以在使用帧动画时应尽量避免使用过多尺寸较大的图片。
View动画是对View的影像做操作,并不能真正改变View的位置参数,包括宽和高,并且如果希望动画后的状态得以保留,还必须将fillAfter属性设置为true,否则动画完成后,其动画结果会消失。