1. 程式人生 > >Android自定義控制元件:動畫類---逐幀動畫AnimationDrawable

Android自定義控制元件:動畫類---逐幀動畫AnimationDrawable

1:概述

            Android動畫包括View Animation(檢視動畫)Property Animator(屬性動畫),而View Animation包括Tween Animation(補間動畫)和Frame Animation(逐幀動畫);補間動畫主Animation(ScaleAnimation、 AlphaAnimation、RotateAnimation、TranslateAnimation)為主,而逐幀動畫則是以AnimationDrawable為主。

2:定義逐幀動畫

定義逐幀動畫非常簡單,只要在<animation-list.../>中使用<item.../>子元素定義動畫的全部幀,並指定各幀的持續時間即可
<?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/scenery1"
    android:duration="1000"/>
 <item
        android:drawable="@drawable/scenery2"
        android:duration="1000"
        />
    <item
        android:drawable="@drawable/scenery3"
        android:duration="1000"
        />
    <item
        android:drawable="@drawable/scenery4"
        android:duration="1000"
        />
    <item
        android:drawable="@drawable/scenery5"
        android:duration="1000"
        />
</animation-list>
上面語法格式中android:onshot控制該動畫是否迴圈播放,如果該引數指定為true,則動畫將不會迴圈播放;否則該動畫將會迴圈播放。每個<item.../>子元素增加一幀。 接下來就可用ImageView把AnimationDrawable顯示出來,習慣上把AnimationDrawable設成ImageView的背景即可。 需要指出的是:AnimationDrawable代表的動畫預設是不播放的,必須在程式中啟動動畫播放才可以。AnimationDrawable提供如下兩個方法開始、停止動畫。  1> start():開始播放動畫  2> stop(): 停止播放動畫

3:新增的幀數過多產生OOM的解決

<span style="font-size:18px;">private void loadBitmap(){
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPurgeable=true;
        options.inInputShareable=true;
        //設定該屬性可獲得圖片的長寬等資訊,但是避免了不必要的提前載入動畫
        options.inJustDecodeBounds=false;
        InputStream is=null;
        int[] raw={
                R.raw.scenery1,R.raw.scenery2,R.raw.scenery3,R.raw.scenery4,R.raw.scenery5
        };
        Bitmap[] mbitMap=new Bitmap[5];
        for(int i=0,j=0;i<5&&j<5;i++,j++){
            is=getResources().openRawResource(raw[i]);
            Bitmap bitmap =BitmapFactory.decodeStream(is, null, options);
            mbitMap[j]=bitmap;
        }

        AnimationDrawable clipDrawable= new AnimationDrawable();
        for(int i=0;i<5;i++){
            clipDrawable.addFrame(new BitmapDrawable(mbitMap[i]), 50);
        }
        clipDrawable.setOneShot(false);
        animationDrawable=clipDrawable;
        iv_frame.setBackground(animationDrawable);
    }</span>
setbackgroundResource()這種方法在設定animationDrawable動畫的時候,是會在java層和native層產生兩個例項的,而高畫素bitmap圖是特別佔記憶體的,所以容易產生記憶體溢位問題,而我找到的最好解決方法是,不適用setBackgroundResource()這個方法而是首先使用decodeStream()這個方法讀入bitmap位元組碼的流,而這個方法與decodeResource等其他方法相比,最好的地方在於它僅僅在native層也就是底層產生一個例項,但不會在java層使用createBitMap()方法產生例項,因此極大地減少了記憶體的佔用,否則當讀入20多張大圖的時候很容易記憶體溢位。