一、前言
在进行Android开发时,产品经理或交互设计师为提升用户体验会经常咨询Android工程师,某某动画能不能实现?好不好实现?等一系列问题。此时只有对Android的动画系统有足够的了解才能比较明确给出准确答复。众所周知,Android系统提供了三种动画:
Tween Animation :View动画,是通过对view对象进行图像变换(平移、缩放、旋转、透明度),并且View动画支持自定义。
Drawable Animation :帧动画,通过顺序播放一系列图像从而产生动画效果。图片过多过大时容易造成OOM。
Property Animation :属性动画,这是在android3.0(API11)之后引进的全新动画,可以通过改变任何对象的属性来达到动画效果。
本篇先介绍View动画、帧动画,属性动画将在后续文章进行介绍。
二、View动画
View动画是对View对象实现动画效果,支持平移、缩放、旋转和透明度这四种动画,这四种动画可通过XML或Android代码来定义,通过XML文件定义更具有可读性和可重用性,所以建议使用XML的方式来定义View动画。下面以表格的方式介绍这两种实现方式对应关系:
1)、定义动画
首先通过XML文件方式在res/anim/下新建View动画文view_animation_deom.xml。此文件中的描述是有固定的语法。如:
<?xml version="1.0" encoding="utf-8"?>
<set
android:interpolator="@[package:]anim/interpolator_resource"
android:shareInterpolator=["true" | "false"] >
<alpha
android:fromAlpha="float"
android:toAlpha="float" />
<scale
android:fromXScale="float"
android:toXScale="float"
android:fromYScale="float"
android:toYScale="float"
android:pivotX="float"
android:pivotY="float" />
<translate
android:fromXDelta="float"
android:toXDelta="float"
android:fromYDelta="float"
android:toYDelta="float" />
<rotate
android:fromDegrees="float"
android:toDegrees="float"
android:pivotX="float"
android:pivotY="float" />
<set>
...
</set>
</set>
从上述文件可以看出,可以通过这种方式定义单个动画,也可以定义组合动画。详细看看文件中出现的标签所表示的含义。
<set>:表示动画集合,对应AnimationSet类,它可以对四种动画任意组合,也可以嵌套其它动画集合,常用的属性有:
xml属性 | java方法 | 含义 |
---|---|---|
android:duration | setDuration(long) | 动画持续时间,毫秒(ms)为单位 |
android:interpolator | setInterpolator(Interpolator) | 设定插值器,影响动画的执行速度 |
android:shareInterpolator | setShareInterpolator(boolean) | 集合中动画是否和集合共享同一个插值器 |
android:repeatCount | setRepeatCount(int) | 动画重复次数 |
android:repeatMode | setRepeatMode(int) | 动画重复类型有两个值,reverse表示倒序回放,restart表示从头播放 |
这些xml属性也可以在<alpha>、 <scale>、<translate>、<rotate>标签中使用。
<alpha>:表示透明度动画,对应AlphaAnimation,通过它可以改变View的透明度,它的属性含义及对应在AlphaAnimation构造函数中的参数如下:
xml属性 | java方法 | 含义 |
---|---|---|
android:fromAlpha | AlphaAnimation(float fromAlpha, …) | 动画初始透明度(0.0到1.0,0.0是全透明,1.0是不透明) |
android:toAlpha | AlphaAnimation(…, float toAlpha) | 动画结束透明度(0.0到1.0,0.0是全透明,1.0是不透明) |
<scale>:表示缩放动画,对应ScaleAnimation,通过它可以实现View的放大及缩小效果,其属性含义及对应在ScaleAnimation构造函数中的参数如下:
xml属性 | java方法 | 含义 |
---|---|---|
android:fromXScale | ScaleAnimation(float fromX, …) | 水平方向缩放的起始值 |
android:toXScale | ScaleAnimation(…, float toX, …) | 水平方向缩放的结束值 |
android:fromYScale | ScaleAnimation(…, float fromY, …) | 垂直方向缩放的起始值 |
android:toYScale | ScaleAnimation(…, float toY, …) | 垂直方向缩放的结束值 |
android:pivotX | ScaleAnimation(…, float pivotX, …) | 缩放的轴点的x坐标 |
android:pivotY | ScaleAnimation(…, float pivotY) | 缩放的轴点的y坐标 |
<translate>:表示平移动画,对应TranslateAnimation类,通过它可以实现View在水平或垂直方向的平移效果,其属性含义及对应在TranslateAnimation构造函数中的参数如下:
xml属性 | java方法 | 含义 |
---|---|---|
android:fromXDelta | TranslateAnimation(float fromXDelta, …) | 表示x的起始值 |
android:toXDelta | TranslateAnimation(...,float toXDelta, …) | 表示x的结束值 |
android:fromYDelta | TranslateAnimation(...,float fromYDelta, …) | 表示y的起始值 |
android:toYDelta | TranslateAnimation(...,float toYDelta) | 表示y的结束值 |
<rotate>:表示旋转动画,对应RotateAnimation类,通过它可以实现View的旋转效果,其属性含义及对应在RotateAnimation构造函数中的参数如下:
xml属性 | java方法 | 含义 |
---|---|---|
android:fromDegrees | RotateAnimation(float fromDegrees, …) | 表示旋转起始角度 正代表顺时针度数,负代表逆时针度数 |
android:toDegrees | RotateAnimation(…, float toDegrees, …) | 表示旋转结束角度 |
android:pivotX | RotateAnimation(…, float pivotX, …) | 旋转在x坐标上的轴点 |
android:pivotY | RotateAnimation(…, float pivotY) | 旋转在y坐标上的轴点 |
2)、如何执行上述定义的动画?
很简单,通过如下代码就能执行在xml中定义的动画
ImageView mImgAnim = (ImageView) findViewById(R.id.iv_anim_demo);
Animation demoAnimation = AnimationUtils.loadAnimation(this, R.anim.view_animation_demo);
mImgAnim.startAnimation(demoAnimation);
除了通过XML定义动画外,还可以通过在Android代码来实现上述组合动画:
public void startAnimationSet() {
//创建动画,参数表示他的子动画是否共用一个插值器
AnimationSet animationSet = new AnimationSet(true);
//添加透明度动画
animationSet.addAnimation(new AlphaAnimation(1.0f, 0.0f));
//添加旋转动画
animationSet.addAnimation(new RotateAnimation(0f, 180f,50,50%));
//设置插值器
animationSet.setInterpolator(new LinearInterpolator());
//设置动画持续时长
animationSet.setDuration(3000);
//设置动画结束之后是否保持动画的目标状态
animationSet.setFillAfter(true);
//设置动画结束之后是否保持动画开始时的状态
animationSet.setFillBefore(false);
//设置重复模式
animationSet.setRepeatMode(AnimationSet.REVERSE);
//设置重复次数
animationSet.setRepeatCount(AnimationSet.INFINITE);
//设置动画延时时间
animationSet.setStartOffset(2000);
//开始动画
mImgAnim.startAnimation(animationSet);
//取消动画
animationSet.cancel();
//释放资源
animationSet.reset();
}
3)、View动画监听
可以通过Animation的setAnimationLister方法来监听View动画的执行过程,举个例子,如下所示:
mImgAnim.setAnimationListener(new Animation.AnimationListener() {
//动画开始的时候触发
@Override
public void onAnimationStart(Animation animation) {
}
//动画结束的时候触发
@Override
public void onAnimationEnd(Animation animation) {
}
//动画重新执行的时候触发
@Override
public void onAnimationRepeat(Animation animation) {
}
});
三、帧动画
帧动画本质上也属于View动画,但帧动画的表现形式和上述四种View动画效果不太一样。帧动画是顺序播放一组预先定义好的图片,实现类似播放幻灯片一样的动画效果。Android系统通过AnimationDrawable来使用帧动画。实现方式是通过XMl定义一个AnimationDrawable,例:
<?xml version="1.0" encoding="utf-8"?>
<animation-list
<item
android:drawable="@drawable/iv_1"
android:duration="100" />
<item
android:drawable="@drawable/iv_2"
android:duration="300" />
<item
android:drawable="@drawable/iv_3"
android:duration="500" />
</animation-list>
然后将通过如下方式即可执行动画:
ImageView frameAnimImg = (ImageView) findViewById(R.id.iv_frame_anim);
frameAnimImg.setImageResource(R.drawable.frame_anim_demo);
AnimationDrawable animationDrawable = (AnimationDrawable) frameAnimImg.getDrawable();
animationDrawable.start();
四、总结
本文首先介绍了View动画如何通过XML定义或代码定义的实现方式及简单使用,当然相对简单,更进阶的内容并未介绍,比如插值器,插值器相关内容会在后续介绍属性动画中再详情介绍,然后介绍了帧动画实现。水平有限,不足及不对之处欢迎指出。