在写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" 删除即可。