Android动画——逐帧动画

1、概述
Android 平台有一套完整的动画框架,在Android3.0之前有两种动画,一种方式是补间动画 Tween Animation、另一种叫逐帧动画 Frame Animation(也称Drawable Animation )。这两种被归类为View Animation。 Android3.0以后增加了属性动画 Property Animation,这样子动画就分成两部分:
Android动画——逐帧动画
2.使用
现在就从Drawable Animation开始说起吧。如上所述,Drawable Animation就是逐帧动画,如果大家看过老式的电影就很容易理解他的原理了,他就像电影胶带一样,按一定频率逐帧播放,使用它之前必须先定义好各个帧。在Android中逐帧动画需要得到AnimationDrawable类的支持,它位于"android.graphics.drawable.AnimationDrawable"包下,是Drawable的间接子类。它主要用来创建一个逐帧动画,并且可以对帧进行拉伸。在Android中提供了两种方式定义AnimationDrawable:XML定义资源文件和Java代码创建,采用XML的方式格式如下:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"  
    android:oneshot="true"|"false">  
    <item android:drawable="@drawable/pic_name1" android:duration="integer" />  
    <item android:drawable="@drawable/pic_name2" android:duration="integer" />  
    <item android:drawable="@drawable/pic_name3" android:duration="integer" />  
    <item android:drawable="@drawable/pic_name4" android:duration="integer" />  
</animation-list>  

其中android:oneshot属性控制该动画播放次数,等于true时则不会循环播放,否则循环播放。<item/>标签定义各个帧显示的图片,显示顺序依照<item/>定义顺序。 然后把AnimationDrawable对象设置为View的背景即可。Android下所有的资源文件均要放在/res目录下,对于动画帧的资源需要当成一个Drawable,所以需要把它放在/res/Drawable目录下。

使用Java代码创建帧动画的方式:通过创建AnimationDrawable对象,然后调用addFrame(Drawable frame,int duration)方法想动画中添加帧,它可以设置添加动画帧的Drawable和持续时间,每调用一次,就会向<animation-list .../>元素中添加一个<item.../>子元素。


下面写一个例子,模仿我们常见的加载界面,界面布局中只有一个居中的ImageView就不列出了。相对重要的是,我们需要定义一个xml文件描述各个帧,如下:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false" >
<item
android:drawable="@drawable/l"
android:duration="500"/>
<item
android:drawable="@drawable/o"
android:duration="500"/>
<item
android:drawable="@drawable/a"
android:duration="500"/>
<item
android:drawable="@drawable/d"
android:duration="500"/>
<item
android:drawable="@drawable/i"
android:duration="500"/>
<item
android:drawable="@drawable/n"
android:duration="500"/>
<item
android:drawable="@drawable/g"
android:duration="500"/>

</animation-list>

只有AnimationDrawable对象还不能完成播放动画的功能,还需要AnimationDrawable其他的一些方法来操作逐帧动画,下面简单介绍一下AnimationDrawable的常用方法:
void start():开始播放逐帧动画。
void stop():停止播放逐帧动画。
void addFrame(Drawable frame,int duration):为AnimationDrawable添加一帧,并设置持续时间。
int getDuration(int i):得到指定index的帧的持续时间。
Drawable getFrame(int index):得到指定index的帧Drawable。
int getNumberOfFrames():得到当前AnimationDrawable的所有帧数量。
boolean isOneShot():当前AnimationDrawable是否执行一次,返回true执行一次,false循环播放。
boolean isRunning():当前AnimationDrawable是否正在播放。
void setOneShot(boolean oneShot):设置AnimationDrawable是否执行一次,true执行一次,false循环播放

Activity类如下:
public class DrawableAnimationActivity extends Activity {

private ImageView mImageViewLoading;
private ImageView mImageViewJava;
private AnimationDrawable loadingAnimation;
private AnimationDrawable javaAnimation;
private Button mButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drawable_animation);
mImageViewLoading = (ImageView) findViewById(R.id.iv_drawable_loading);
mImageViewJava = (ImageView) findViewById(R.id.iv_drawable_java);
mButton = (Button) findViewById(R.id.btn_drawable_java);
loadingAnimation = (AnimationDrawable) mImageViewLoading
.getBackground();
// 采用java代码方式创建动画
mImageViewJava.setBackgroundResource(R.drawable.loading);
javaAnimation = (AnimationDrawable) mImageViewJava.getBackground();

mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
javaAnimation.start();
}
});
}

/**
* 触摸屏幕,结束动画
*/
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
loadingAnimation.stop();
return true;
}
return super.onTouchEvent(event);
}

/**
* activity显示到屏幕则开启动画
*/
@Override
public void onWindowFocusChanged(boolean hasFocus) {
// TODO Auto-generated method stub
super.onWindowFocusChanged(hasFocus);
if (hasFocus)
loadingAnimation.start();
}
}

实现的功能是:activity一启动,则动画开始,触摸屏幕时动画停止,代码比较容易理解,唯一需要注意的是,不能在onCreate()方法中调用AnimationDrawable的start()方法,因为此时AnimationDrawable还未真正加载到界面中。所以,如果想启动界面就自动运行动画,可以在OnWindowFocusChanged(boolean hasFocus)中启动动画。
效果如下:
Android动画——逐帧动画
使用Frame Animation注意以下问题:
  1. 要在代码中调用Imageview的setBackgroundResource方法,如果直接在XML布局文件中设置其src属性当触发动画时会强制退出。
  2. 在动画start()之前要先stop(),不然在第一次动画之后会停在最后一帧,这样动画就只会触发一次。
  3. 最后一点是SDK中提到的,不要在onCreate中调用start,因为AnimationDrawable还没有完全跟Window相关联,在onCreate()方法中,View并未完全显示(同理,在此方法中测量某个View的宽高,常得到0值。也同理SurfaceHolder要增加Callback方法)。如果想要界面显示时就开始动画的话,可以在onWindowFoucsChanged()中调用start()。

参考:


上一篇:在Unix环境下mount ISO文件


下一篇:【Android开发】图形图像处理技术-实现Android动画的两种方式