Android動畫之Frame Animation
在開始例項講解之前,先引用官方文件中的一段話:
Frame動畫是一系列圖片按照一定的順序展示的過程,和放電影的機制很相似,我們稱為逐幀動畫。Frame動畫可以被定義在XML檔案中,也可以完全編碼實現。
如果被定義在XML檔案中,我們可以放置在/res下的anim或drawable目錄中(/res/[anim | drawable]/filename.xml),檔名可以作為資源ID在程式碼中引用;如果由完全由編碼實現,我們需要使用到AnimationDrawable物件。
如果是將動畫定義在XML檔案中的話,語法如下:
[html] view plain copy print?- <?xmlversion
- <animation-listxmlns:android=“http://schemas.android.com/apk/res/android”
- android:oneshot=[“true” | “false”] >
- <item
- android:drawable=“@[package:]drawable/drawable_resource_name”
- android:duration=“integer”/>
- </animation-list>
<?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="@[package:]drawable/drawable_resource_name" android:duration="integer" /> </animation-list>
需要注意的是:
<animation-list>元素是必須的,並且必須要作為根元素,可以包含一或多個<item>元素;android:onshot如果定義為true的話,此動畫只會執行一次,如果為false則一直迴圈。
<item>元素代表一幀動畫,android:drawable指定此幀動畫所對應的圖片資源,android:druation代表此幀持續的時間,整數,單位為毫秒。
文件接下來的示例我就不在解說了,因為接下來我們也要結合自己的例項演示一下這個過程。
我們新建一個名為anim的工程,將四張連續的圖片分別命名為f1.png,f2.png,f3.png,f4.png,放於drawable目錄,然後新建一個frame.xml檔案:
- <?xmlversion=“1.0”encoding=“utf-8”?>
- <animation-listxmlns:android=“http://schemas.android.com/apk/res/android”
- android:oneshot=“false”>
- <itemandroid:drawable=“@drawable/f1”android:duration=“300”/>
- <itemandroid:drawable=“@drawable/f2”android:duration=“300”/>
- <itemandroid:drawable=“@drawable/f3”android:duration=“300”/>
- <itemandroid:drawable=“@drawable/f4”android:duration=“300”/>
- </animation-list>
<?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/f1" android:duration="300" />
<item android:drawable="@drawable/f2" android:duration="300" />
<item android:drawable="@drawable/f3" android:duration="300" />
<item android:drawable="@drawable/f4" android:duration="300" />
</animation-list>
我們可以將frame.xml檔案放置於drawable或anim目錄,官方文件上是放到了drawable中了,大家可以根據喜好來放置,放在這兩個目錄都是可以執行的。
然後介紹一下佈局檔案res/layout/frame.xml:
[html] view plain copy print?- <?xmlversion=“1.0”encoding=“utf-8”?>
- <LinearLayout
- xmlns:android=“http://schemas.android.com/apk/res/android”
- android:orientation=“vertical”
- android:layout_width=“fill_parent”
- android:layout_height=“fill_parent”>
- <ImageView
- android:id=“@+id/frame_image”
- android:layout_width=“fill_parent”
- android:layout_height=“fill_parent”
- android:layout_weight=“1”/>
- <Button
- android:layout_width=“fill_parent”
- android:layout_height=“wrap_content”
- android:text=“stopFrame”
- android:onClick=“stopFrame”/>
- <Button
- android:layout_width=“fill_parent”
- android:layout_height=“wrap_content”
- android:text=“runFrame”
- android:onClick=“runFrame”/>
- </LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:id="@+id/frame_image"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="stopFrame"
android:onClick="stopFrame"/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="runFrame"
android:onClick="runFrame"/>
</LinearLayout>
我們定義了一個ImageView作為動畫的載體,然後定義了兩個按鈕,分別是停止和啟動動畫。
接下來介紹一下如何通過載入動畫定義檔案來實現動畫的效果。我們首先會這樣寫:
[java] view plain copy print?- package com.scott.anim;
- import android.app.Activity;
- import android.graphics.drawable.AnimationDrawable;
- import android.graphics.drawable.Drawable;
- import android.os.Bundle;
- import android.view.View;
- import android.widget.ImageView;
- publicclass FrameActivity extends Activity {
- private ImageView image;
- @Override
- protectedvoid onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.frame);
- image = (ImageView) findViewById(R.id.frame_image);
- image.setBackgroundResource(R.anim.frame);
- AnimationDrawable anim = (AnimationDrawable) image.getBackground();
- anim.start();
- }
- }
package com.scott.anim;
import android.app.Activity;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
public class FrameActivity extends Activity {
private ImageView image;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.frame);
image = (ImageView) findViewById(R.id.frame_image);
image.setBackgroundResource(R.anim.frame);
AnimationDrawable anim = (AnimationDrawable) image.getBackground();
anim.start();
}
}
看似十分完美,跟官方文件上寫的一樣,然而當我們執行這個程式時會發現,它只停留在第一幀,並沒有出現我們期望的動畫,也許你會失望的說一句:“Why?”,然後你把相應的程式碼放在一個按鈕的點選事件中,動畫就順利執行了,再移回到onCreate中,還是沒效果,這個時候估計你會氣急敗壞的吼一句:“What the fuck!”。但是,什麼原因呢?如何解決呢?
出現這種現象是因為當我們在onCreate中呼叫AnimationDrawable的start方法時,視窗Window物件還沒有完全初始化,AnimationDrawable不能完全追加到視窗Window物件中,那麼該怎麼辦呢?我們需要把這段程式碼放在onWindowFocusChanged方法中,當Activity展示給使用者時,onWindowFocusChanged方法就會被呼叫,我們正是在這個時候實現我們的動畫效果。當然,onWindowFocusChanged是在onCreate之後被呼叫的,如圖:
然後我們需要重寫一下程式碼:
[java] view plain copy print?- package com.scott.anim;
- import android.app.Activity;
- import android.graphics.drawable.AnimationDrawable;
- import android.graphics.drawable.Drawable;
- import android.os.Bundle;
- import android.view.View;
- import android.widget.ImageView;
- publicclass FrameActivity extends Activity {
- private ImageView image;
- @Override
- protectedvoid onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.frame);
- image = (ImageView) findViewById(R.id.frame_image);
- }
- @Override
- publicvoid onWindowFocusChanged(boolean hasFocus) {
- super.onWindowFocusChanged(hasFocus);
- image.setBackgroundResource(R.anim.frame);
- AnimationDrawable anim = (AnimationDrawable) image.getBackground();
- anim.start();
- }
- }
package com.scott.anim;
import android.app.Activity;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
public class FrameActivity extends Activity {
private ImageView image;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.frame);
image = (ImageView) findViewById(R.id.frame_image);
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
image.setBackgroundResource(R.anim.frame);
AnimationDrawable anim = (AnimationDrawable) image.getBackground();
anim.start();
}
}
執行一下,動畫就可以正常顯示了。
如果在有些場合,我們需要用純程式碼方式實現一個動畫,我們可以這樣寫:
[java] view plain copy print?- AnimationDrawable anim = new AnimationDrawable();
- for (int i = 1; i <= 4; i++) {
- int id = getResources().getIdentifier(“f” + i, “drawable”, getPackageName());
- Drawable drawable = getResources().getDrawable(id);
- anim.addFrame(drawable, 300);
- }
- anim.setOneShot(false);
- image.setBackgroundDrawable(anim);
- anim.start();
AnimationDrawable anim = new AnimationDrawable();
for (int i = 1; i <= 4; i++) {
int id = getResources().getIdentifier("f" + i, "drawable", getPackageName());
Drawable drawable = getResources().getDrawable(id);
anim.addFrame(drawable, 300);
}
anim.setOneShot(false);
image.setBackgroundDrawable(anim);
anim.start();
完整的FrameActivity.java程式碼如下:
[java] view plain copy print?- package com.scott.anim;
- import android.app.Activity;
- import android.graphics.drawable.AnimationDrawable;
- import android.graphics.drawable.Drawable;
- import android.os.Bundle;
- import android.view.View;
- import android.widget.ImageView;
- publicclass FrameActivity extends Activity {
- private ImageView image;
- @Override
- protectedvoid onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.frame);
- image = (ImageView) findViewById(R.id.frame_image);
- }
- @Override
- publicvoid onWindowFocusChanged(boolean hasFocus) {
- super.onWindowFocusChanged(hasFocus);
- image.setBackgroundResource(R.anim.frame); //將動畫資原始檔設定為ImageView的背景
- AnimationDrawable anim = (AnimationDrawable) image.getBackground(); //獲取ImageView背景,此時已被編譯成AnimationDrawable
- anim.start(); //開始動畫
- }
- publicvoid stopFrame(View view) {
- AnimationDrawable anim = (AnimationDrawable) image.getBackground();
- if (anim.isRunning()) { //如果正在執行,就停止
- anim.stop();
- }
- }
- publicvoid runFrame(View view) {
- //完全編碼實現的動畫效果
- AnimationDrawable anim = new AnimationDrawable();
- for (int i = 1; i <= 4; i++) {
- //根據資源名稱和目錄獲取R.java中對應的資源ID
- int id = getResources().getIdentifier(“f” + i, “drawable”, getPackageName());
- //根據資源ID獲取到Drawable物件
- Drawable drawable = getResources().getDrawable(id);
- //將此幀新增到AnimationDrawable中
- anim.addFrame(drawable, 300);
- }
- anim.setOneShot(false); //設定為loop
- image.setBackgroundDrawable(anim); //將動畫設定為ImageView背景
- anim.start(); //開始動畫
- }
- }
package com.scott.anim;
import android.app.Activity;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
public class FrameActivity extends Activity {
private ImageView image;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.frame);
image = (ImageView) findViewById(R.id.frame_image);
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
image.setBackgroundResource(R.anim.frame); //將動畫資原始檔設定為ImageView的背景
AnimationDrawable anim = (AnimationDrawable) image.getBackground(); //獲取ImageView背景,此時已被編譯成AnimationDrawable
anim.start(); //開始動畫
}
public void stopFrame(View view) {
AnimationDrawable anim = (AnimationDrawable) image.getBackground();
if (anim.isRunning()) { //如果正在執行,就停止
anim.stop();
}
}
public void runFrame(View view) {
//完全編碼實現的動畫效果
AnimationDrawable anim = new AnimationDrawable();
for (int i = 1; i <= 4; i++) {
//根據資源名稱和目錄獲取R.java中對應的資源ID
int id = getResources().getIdentifier("f" + i, "drawable", getPackageName());
//根據資源ID獲取到Drawable物件
Drawable drawable = getResources().getDrawable(id);
//將此幀新增到AnimationDrawable中
anim.addFrame(drawable, 300);
}
anim.setOneShot(false); //設定為loop
image.setBackgroundDrawable(anim); //將動畫設定為ImageView背景
anim.start(); //開始動畫
}
}
好,先到這裡,謝謝大家。文章轉載自http://blog.csdn.net/liuhe688/article/details/6657776