1. 程式人生 > >Android動畫之Frame Animation

Android動畫之Frame Animation

在開始例項講解之前,先引用官方文件中的一段話:

Frame動畫是一系列圖片按照一定的順序展示的過程,和放電影的機制很相似,我們稱為逐幀動畫。Frame動畫可以被定義在XML檔案中,也可以完全編碼實現。

如果被定義在XML檔案中,我們可以放置在/res下的anim或drawable目錄中(/res/[anim | drawable]/filename.xml),檔名可以作為資源ID在程式碼中引用;如果由完全由編碼實現,我們需要使用到AnimationDrawable物件。

如果是將動畫定義在XML檔案中的話,語法如下:

[html] view plain copy print?
  1. <?xmlversion
    =“1.0”encoding=“utf-8”?>
  2. <animation-listxmlns:android=“http://schemas.android.com/apk/res/android”
  3.     android:oneshot=[“true” | “false”] >
  4.     <item
  5.         android:drawable=“@[package:]drawable/drawable_resource_name”
  6.         android:duration=“integer”/>
  7. </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檔案:

[html] view plain copy print?
  1. <?xmlversion=“1.0”encoding=“utf-8”?>
  2. <animation-listxmlns:android=“http://schemas.android.com/apk/res/android”
  3.     android:oneshot=“false”>
  4.     <itemandroid:drawable=“@drawable/f1”android:duration=“300”/>
  5.     <itemandroid:drawable=“@drawable/f2”android:duration=“300”/>
  6.     <itemandroid:drawable=“@drawable/f3”android:duration=“300”/>
  7.     <itemandroid:drawable=“@drawable/f4”android:duration=“300”/>
  8. </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?
  1. <?xmlversion=“1.0”encoding=“utf-8”?>
  2. <LinearLayout
  3.   xmlns:android=“http://schemas.android.com/apk/res/android”
  4.   android:orientation=“vertical”
  5.   android:layout_width=“fill_parent”
  6.   android:layout_height=“fill_parent”>
  7.   <ImageView
  8.     android:id=“@+id/frame_image”
  9.     android:layout_width=“fill_parent”
  10.     android:layout_height=“fill_parent”
  11.     android:layout_weight=“1”/>
  12.   <Button
  13.     android:layout_width=“fill_parent”
  14.     android:layout_height=“wrap_content”
  15.     android:text=“stopFrame”
  16.     android:onClick=“stopFrame”/>
  17.   <Button
  18.     android:layout_width=“fill_parent”
  19.     android:layout_height=“wrap_content”
  20.     android:text=“runFrame”
  21.     android:onClick=“runFrame”/>
  22. </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?
  1. package com.scott.anim;  
  2. import android.app.Activity;  
  3. import android.graphics.drawable.AnimationDrawable;  
  4. import android.graphics.drawable.Drawable;  
  5. import android.os.Bundle;  
  6. import android.view.View;  
  7. import android.widget.ImageView;  
  8. publicclass FrameActivity extends Activity {  
  9.     private ImageView image;  
  10.     @Override
  11.     protectedvoid onCreate(Bundle savedInstanceState) {  
  12.         super.onCreate(savedInstanceState);  
  13.         setContentView(R.layout.frame);  
  14.         image = (ImageView) findViewById(R.id.frame_image);  
  15.         image.setBackgroundResource(R.anim.frame);  
  16.         AnimationDrawable anim = (AnimationDrawable) image.getBackground();  
  17.         anim.start();  
  18.     }  
  19. }  
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?
  1. package com.scott.anim;  
  2. import android.app.Activity;  
  3. import android.graphics.drawable.AnimationDrawable;  
  4. import android.graphics.drawable.Drawable;  
  5. import android.os.Bundle;  
  6. import android.view.View;  
  7. import android.widget.ImageView;  
  8. publicclass FrameActivity extends Activity {  
  9.     private ImageView image;  
  10.     @Override
  11.     protectedvoid onCreate(Bundle savedInstanceState) {  
  12.         super.onCreate(savedInstanceState);  
  13.         setContentView(R.layout.frame);  
  14.         image = (ImageView) findViewById(R.id.frame_image);  
  15.     }  
  16.     @Override
  17.     publicvoid onWindowFocusChanged(boolean hasFocus) {  
  18.         super.onWindowFocusChanged(hasFocus);  
  19.         image.setBackgroundResource(R.anim.frame);  
  20.         AnimationDrawable anim = (AnimationDrawable) image.getBackground();  
  21.         anim.start();  
  22.     }  
  23. }  
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?
  1. AnimationDrawable anim = new AnimationDrawable();  
  2. for (int i = 1; i <= 4; i++) {  
  3.     int id = getResources().getIdentifier(“f” + i, “drawable”, getPackageName());  
  4.     Drawable drawable = getResources().getDrawable(id);  
  5.     anim.addFrame(drawable, 300);  
  6. }  
  7. anim.setOneShot(false);  
  8. image.setBackgroundDrawable(anim);  
  9. 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?
  1. package com.scott.anim;  
  2. import android.app.Activity;  
  3. import android.graphics.drawable.AnimationDrawable;  
  4. import android.graphics.drawable.Drawable;  
  5. import android.os.Bundle;  
  6. import android.view.View;  
  7. import android.widget.ImageView;  
  8. publicclass FrameActivity extends Activity {  
  9.     private ImageView image;  
  10.     @Override
  11.     protectedvoid onCreate(Bundle savedInstanceState) {  
  12.         super.onCreate(savedInstanceState);  
  13.         setContentView(R.layout.frame);  
  14.         image = (ImageView) findViewById(R.id.frame_image);  
  15.     }  
  16.     @Override
  17.     publicvoid onWindowFocusChanged(boolean hasFocus) {  
  18.         super.onWindowFocusChanged(hasFocus);  
  19.         image.setBackgroundResource(R.anim.frame);  //將動畫資原始檔設定為ImageView的背景
  20.         AnimationDrawable anim = (AnimationDrawable) image.getBackground(); //獲取ImageView背景,此時已被編譯成AnimationDrawable
  21.         anim.start();   //開始動畫
  22.     }  
  23.     publicvoid stopFrame(View view) {  
  24.         AnimationDrawable anim = (AnimationDrawable) image.getBackground();  
  25.         if (anim.isRunning()) { //如果正在執行,就停止
  26.             anim.stop();  
  27.         }  
  28.     }  
  29.     publicvoid runFrame(View view) {  
  30.         //完全編碼實現的動畫效果
  31.         AnimationDrawable anim = new AnimationDrawable();  
  32.         for (int i = 1; i <= 4; i++) {  
  33.             //根據資源名稱和目錄獲取R.java中對應的資源ID
  34.             int id = getResources().getIdentifier(“f” + i, “drawable”, getPackageName());  
  35.             //根據資源ID獲取到Drawable物件
  36.             Drawable drawable = getResources().getDrawable(id);  
  37.             //將此幀新增到AnimationDrawable中
  38.             anim.addFrame(drawable, 300);  
  39.         }  
  40.         anim.setOneShot(false); //設定為loop
  41.         image.setBackgroundDrawable(anim);  //將動畫設定為ImageView背景
  42.         anim.start();   //開始動畫
  43.     }  
  44. }  
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