在写Frame by Frame Animation之前先介绍一下android中支持的动画类型。android有两种机制让用户创建简单的动画——tweened animation 和 frame by frame animation 。 其中tweened animation 实现 view 的诸如 移动 、大小变化、旋转等;frame by frame animation 是加载一系列的图片顺序的播放他们。处理 tweened animation的api 在包 android.view.animation中,而处理 frame by frame animation 的 在 AnimationDrawable 中。
下面重点说一下frame by frame animation (帧动画):
Frame动画是一系列图片按照一定的顺序展示的过程,和放电影的机制很相似,我们称为逐帧动画。Frame动画可以被定义在XML文件中,也可以完全编码实现。
如果被定义在XML文件中,我们可以放置在/res下的anim或drawable目录中,文件名可以作为资源ID在代码中引用;如果由完全由编码实现,我们需要使用到AnimationDrawable对象。
1、将动画定义在xml文件中
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false"
android:id="@+id/frame_anim_list" >
<item
android:drawable="@drawable/ting_frame_0"
android:duration="50">
</item>
<item
android:drawable="@drawable/ting_frame_0"
android:duration="50">
</item>
<item
android:drawable="@drawable/ting_frame_1"
android:duration="50">
</item>
<item
android:drawable="@drawable/ting_frame_2"
android:duration="50">
</item>
<item
android:drawable="@drawable/ting_frame_3"
android:duration="500">
</item>
<item
android:drawable="@drawable/ting_frame_4"
android:duration="50">
</item>
</animation-list>
其中<animation-list>元素是必须的,并且必须要作为根元素,可以包含一或多个<item>元素;android:onshot如果定义为true的话,此动画只会执行一次,如果为false则一直循环。一个<item>元素代表一帧动画,android:drawable指定此帧动画所对应的图片资源,android:druation代表此帧持续的时间,整数,单位为毫秒。
2、硬编码实现逐帧动画
private final int[] frames = { R.drawable.ting_frame_0,
R.drawable.ting_frame_1, R.drawable.ting_frame_2,
R.drawable.ting_frame_3, R.drawable.ting_frame_4 };
private void createAnim() {
mAd = new AnimationDrawable();
for (int i = 0; i < frames.length; i++) {
mAd.addFrame(getResources().getDrawable(frames[i]), 300);
}
mAd.setOneShot(false);
}
其中mAd是个DrawableAnimation对象。方法setOneShot(false)同xml中的android:oneShot="false" 。
看了半天,发现没有实例是最tmdt的事,有兴趣的朋友可以继续看下面的实例。 首先,我们先准备几张图片命名为 ting_frame_0.png 、
ting_frame_1.png 、ting_frame_2.png 、 ting_frame_3.png 、 ting_frame_4.png 放到drawable目录下 , 并在drawable目录下创建文件 frame_by_frame_anim.xml , 文件内容如下 :
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false"
android:id="@+id/frame_anim_list" >
<item
android:drawable="@drawable/ting_frame_0"
android:duration="300">
</item>
<item
android:drawable="@drawable/ting_frame_0"
android:duration="300">
</item>
<item
android:drawable="@drawable/ting_frame_1"
android:duration="300">
</item>
<item
android:drawable="@drawable/ting_frame_2"
android:duration="300">
</item>
<item
android:drawable="@drawable/ting_frame_3"
android:duration="300">
</item>
<item
android:drawable="@drawable/ting_frame_4"
android:duration="300">
</item>
</animation-list>
layout目录下创建两个xml文件 分别为 activity_main.xml , frame_anim_layout.xml
activity_main.xml主要定义了一些指示操作的view(没用到的view可以删除),其内容如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/frame_anim_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/frame_animation" />
<Button
android:id="@+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button" />
<Button
android:id="@+id/button3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button" />
<Button
android:id="@+id/button4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button" />
<Button
android:id="@+id/button5"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button" />
<Button
android:id="@+id/button6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button" />
<Button
android:id="@+id/button7"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button" />
</LinearLayout>
frame_anim_layout.xml , 定义了用于显示动画容器 ImageView ,其内容如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<!-- android:background="@drawable/frame_by_frame_anim" -->
<ImageView
android:id="@+id/frame_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/app_name"
android:background="@drawable/frame_by_frame_anim"/>
</LinearLayout>
AndroidManifest.xml的内容如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.zt.xy.animation"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="15" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="FrameAnimActivity"></activity>
</application>
</manifest>
同样也使用了两个activity , 它们分别是 MainActivity 和 FrameAnimActivity
MainActivity.java的内容如下:
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener {
private Button mFrameAnim;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
mFrameAnim = (Button) findViewById(R.id.frame_anim_btn);
mFrameAnim.setOnClickListener(this);
}
public void onClick(View v) {
Intent tarIntent;
switch (v.getId()) {
case R.id.frame_anim_btn:
tarIntent = new Intent(this, FrameAnimActivity.class);
this.startActivity(tarIntent);
break;
}
}
}
当点击 “Frame Animation ” 按钮时启动显示动画的activity 。
下面是显示动画的activity FrameAnimActivity.java :
import android.app.Activity;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.widget.ImageView;
public class FrameAnimActivity extends Activity {
private ImageView mFrameImg;
AnimationDrawable mAd;
private final int[] frames = { R.drawable.ting_frame_0,
R.drawable.ting_frame_1, R.drawable.ting_frame_2,
R.drawable.ting_frame_3, R.drawable.ting_frame_4 };
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.frame_anim_layout);
init();
try {
mAd = (AnimationDrawable) mFrameImg.getBackground();
} catch (ClassCastException e) {
mAd = null;
}
// createAnim();
// mFrameImg.setBackground(mAd);
}
private void createAnim() {
mAd = new AnimationDrawable();
for (int i = 0; i < frames.length; i++) {
mAd.addFrame(getResources().getDrawable(frames[i]), 300);
}
mAd.setOneShot(false);
}
@Override
public void onResume() {
super.onResume();
if (mAd != null) {
mAd.start();
}
}
@Override
public void onPause() {
super.onPause();
if (mAd != null) {
mAd.stop();
}
}
private void init() {
mFrameImg = (ImageView) findViewById(R.id.frame_image);
}
}
好了,运行一下,大功告成。
以上使用的是xml中定义的动画,若想硬编码实现逐帧动画,则将onCreate函数中修改为如下内容:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.frame_anim_layout);
init();
// try {
// mAd = (AnimationDrawable) mFrameImg.getBackground();
// } catch (ClassCastException e) {
// mAd = null;
// }
createAnim();
mFrameImg.setBackground(mAd);
}
再将
frame_anim_layout.xml中的
android:background="@drawable/frame_by_frame_anim" 删除即可。