Android进阶知识(十八):View动画、帧动画与View动画的特殊应用
Android进阶知识(十八):View动画、帧动画与View动画的特殊应用
Android的动画可以分为三种:View动画、帧动画和属性动画,其实帧动画也属于View动画的一种,只不过它和平移、旋转等常见的View动画在表现形式上略有不同。
一、View动画
View动画作用对象为View,其通过对场景里的对象不断做图形变换(平移、旋转、缩放、透明度)从而产生动画效果,它是一种渐近式动画,并且View动画支持自定义。
- View动画的种类
View动画的四种变换效果对应着Animation的四个子类:TranslateAnimation、ScaleAnimation、RotateAnimation和AlphaAnimation。如下表所示,这四种动画既可以通过XML来定义,也可以通过代码来定义,对于View动画来说,由于XML格式的动画可读性更好,因此建议采用XML定义。
名称 | 标签 | 子类 | 效果 |
---|---|---|---|
平移动画 | <translate> | TranslateAnimation | 移动View |
缩放动画 | <scale> | ScaleAnimation | 放大或缩小View |
旋转动画 | <rotate> | RotateAnimation | 旋转View |
透明度动画 | <alpha> | AlphaAnimation | 改变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="@[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>
从上面的语法可以看出,View动画既可以是单个动画,也可以由一系列动画组成。<set>标签表示动画集合,对于AnimationSet类,它可以包含若干个动画,并且它的内部也可以嵌套其他动画集合。至于各个属性的的含义具体可以参照博客:Android View动画——alpha、scale等属性用法。
定义了XML动画,应用动画的代码如下所示。
Button mButton = findViewById(R.id.button);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.animations);
mButton.startAnimation(animation);
除了在XML中定义动画外,还可以通过代码来应用动画,一个例子如下所示。
AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
alphaAnimation.setDuration(300);
mButton.startAnimation(alphaAnimation);
另外,通过Animation的setAnimationListener方法可以给View动画添加过程监听,接口如下所示。
public static interface AnimationListener {
void onAnimationStart(Animation animation);
void onAnimationEnd(Animation animation);
void onAnimationRepeat(Animation animation);
}
- 自定义View动画
自定义View动画是一件既简单又复杂的事情。
简单在于,派生一种新动画只需要继承Animation这个抽象类,然后重写它的initialize和applyTransformation方法,在initialize方法中做一些初始化工作,在applyTransformation中进行相应的矩阵变换即可,很多时候需要采用Camera来简化矩阵变换的过程。
说其复杂,在于自定义View动画的过程主要是矩阵变换的过程,而矩阵变换是就会比较复杂。具体可以参考博客:Android View动画——自定义View动画。
二、帧动画
帧动画通过顺序播放一系列图形从而产生动画效果。
不同于View动画,系统提供了另一个类AnimationDrawable来使用帧动画。帧动画的使用需要先通过XML来定义一个AnimationDrawable,如下所示。
// res/drawable/frame_animation.xml
<?xml version="1.0" enconding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false" >
<item android:drawable="@drawable/image1" android:duration="500" />
<item android:drawable="@drawable/image2" android:duration="500" />
<item android:drawable="@drawable/image3" android:duration="500" />
</animation-list>
将上述的Drawable作为View的背景并通过Drawable来播放动画即可。
Button mButton = findViewById(R.id.button);
mButton.setBackgroundResource(R.drawable.frame_animation);
AnimationDrawable drawable = (AnimationDrawable)mButton.getBackground();
drawable.start();
帧动画的使用比较简单,但是比较容易引起OOM,所以在使用帧动画时应尽量避免使用过多尺寸较大的图片。
三、View动画的特殊应用
View动画除了四种形式之外,还可以在一些特殊情景下使用,比如在ViewGroup中可以控制子元素的出场效果,在Activity中可以实现不同Activity之间的切换效果。
- LayoutAnimation
LayoutAnimation作用于ViewGroup,为ViewGroup指定一个动画,使其子元素的出场具有动画效果(通常作用于ListView上)。LayoutAnimation为ViewGroup的子元素添加出场效果的步骤如下。
- 定义LayoutAnimation,代码如下。
// res/anim/anim_layout.xml
<layoutAnimation
xmlns:android="http://schemas.android.com/apk/res/android"
android:delay="0.5"
android:animationOrder="normal"
android:animation="@anim/anim_item" />
属性说明:
属性 | 描述 |
---|---|
android:delay | 表示子元素开始动画的延迟,比如子元素入场动画的时间周期为300ms,那么0.5表示每个子元素依次延迟150ms播放入场动画,第一个延迟150ms,第二个延迟300ms。 |
android:animationOrder | 表示子元素动画的顺序,有normal、reverse和random。normal表示顺序显示;reverse表示逆向显示;randoom表示随机播放入场动画。 |
android:animation | 为子元素指定具体的入场动画 |
- 为子元素指定具体的入场动画,如下所示。
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:interpolator="@android:anim/accelerate_interpolator"
android:shareInterpolator="true" >
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0" />
<translate
android:fromXDelta="500"
android:toXDelta="0" />
</set>
- 为ViewGroup指定android:layoutAnimation属性,如下所示。
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutAnimation="@anim/anim_layout"
android:background="#fff4f7f9" />
除了在XML中指定LayoutAnimation之外,还可以通过LayoutAnimationController来实现,具体代码如下。
ListView listView = layout.findViewById(R.id.list);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.anim_item);
LayoutAnimationController controller = new LayoutAnimationController(animation);
controller.setDelay(0.5f);
controller.setOrder(LayoutAnimatinoController.ORDER_NORMAL);
listView.setLayoutAnimation(controller);
- Activity的切换效果
Activity有默认的切换效果,但是这个效果可以自定义,主要用到overridePendingTransition(int enterAnim, int exitAnim)这个方法,这个方法必须在startActivity(Intent)或者finish()之后被调用才能生效,参数含义如下。
- enterAnim——Activity被打开时,所需的动画资源id。
- exitAnim——Activity被暂停时,所需的动画资源id。
添加自定义切换效果的代码如下所示。
// Activity启动指定切换效果
Intent intent = new Intent(this, TestActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim);
// Activity退出指定切换效果
@Override
public void finish() {
super.finish();
overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim);
}
需要注意的是,overridePendingTransition这个方法必须位于startActivity或者finish的后面,否则动画效果将不起作用。
参考资料:《Android开发艺术探索》