1. 程式人生 > >Android 動畫之逐幀動畫小述

Android 動畫之逐幀動畫小述

一、概述

本節主要介紹下逐幀動畫的基本使用,下面我們就從XML方式建立動畫和程式碼方式建立動畫來分別說下吧

二、逐幀動畫介紹

在開始介紹逐幀動畫之前,先來看一下在本例中我們要實現的逐幀動畫的效果

這裡寫圖片描述

逐幀動畫,我的理解就是將一幀幀的靜態圖片進行有序的展示,利用人眼的視覺暫留現象來呈現給使用者一種連貫的動畫效果。在實際編寫程式碼過程中,我們主要是通過系統提供的AnimationDrawable類來控制逐幀動畫,AnimationDrawable又是何許類也?這是API中給我們的介紹

這裡寫圖片描述

通過API介紹我們知道,AnimationDrawable類一種用於建立逐幀動畫的物件,由一系列可繪製物件定義,該物件可以用作檢視物件的背景。建立逐幀動畫最簡單的方法是在XML檔案中定義動畫,下面來讓我們看下具體的實現吧。

三、 通過xml定義動畫

將我們所需要的圖片放入mipmap資料夾下,當前動畫即由這6幀組成

這裡寫圖片描述

在drawable資料夾下,新建一個anim_frame_load.xml檔案,現在Android Studio只支援將animation-list的xml檔案放在drawable目錄之下

        //res右鍵=>Android Resource File
        =>File name:anim_frame_load(xml檔名字),Resource type:Drawable,Root element:animation-list,Directory name:
drawable(資料夾的名字)

drawable目錄結構如下所示

這裡寫圖片描述

在anim_frame_load.xml檔案中編寫animation-list,並可以設定屬性android:id="selected"和設定是否只播放一次android:oneshot=“false”

    <animation-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@mipmap/load01" android:duration="200">
</item> <item android:drawable="@mipmap/load02" android:duration="200"></item> <item android:drawable="@mipmap/load03" android:duration="200"></item> <item android:drawable="@mipmap/load04" android:duration="200"></item> <item android:drawable="@mipmap/load05" android:duration="200"></item> <item android:drawable="@mipmap/load06" android:duration="200"></item> </animation-list>

這是我們的幀動畫類,通過AnimationDrawable來執行動畫,程式碼比較簡單

    public class FrameAnimationTest extends Activity{
        //動畫物件
        AnimationDrawable animDrawable;
        //新增動畫的控制元件
        ImageView imgLoad;

        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.anim_frame_load);
            initView();
            addClickListener();
        }

        private void initView() {
            imgLoad = (ImageView) findViewById(R.id.img_load);
        }

        private void addClickListener() {
            findViewById(R.id.tv_load_start).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    //開始逐幀動畫
                    startAnimByXml();
                }
            });
            findViewById(R.id.tv_load_stop).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    //結束動畫
                    stopAnim();
                }
            });
        }

        /** xml方式開始動畫*/
        private void startAnimByXml() {
            imgLoad.setBackgroundResource(R.drawable.anim_frame_load);
            animDrawable = (AnimationDrawable) imgLoad.getBackground();
            //如果動畫正在執行,則此方法沒有效果,內部已經判斷了,所以我們不必判斷動畫狀態了
            animDrawable.start();
        }

        /** 結束動畫*/
        private void stopAnim() {
            if(animDrawable != null){
                //如果動畫不執行,此方法沒有效果,內部已經判斷了,所以我們不必判斷動畫狀態了
                animDrawable.stop();
            }
        }

        @Override
        protected void onDestroy() {
            super.onDestroy();
            if(animDrawable != null){
                //當介面銷燬的時候,銷燬animDrawable
                animDrawable = null;
            }
        }
    }

其實幀動畫不僅可以通過xml方式定義,還能在程式碼中直接實現,因為AnimationDrawable類為我們提供了addFrame(Drawable frame, int duration) 這個直接新增幀圖片Drawable物件到動畫中的方法,同時它還提供了一系列設定動畫屬性和獲取狀態的公開方法,下面來讓我們看看具體的實現。

四、 直接在程式碼中實現

將圖片新增到專案mipmap目錄下

這裡寫圖片描述

我們直接在程式碼中通過AnimationDrawable來實現幀動畫,所以就不必編寫xml檔案了,這種方式比較適用於你的專案動畫需要動態擴充套件或者專案對於動畫的靈活性有很高的要求,而如果你更加看重的是動畫的高度複用性,那麼就優先選擇xml定義動畫的方式吧,畢竟這也是API所推薦的方式。

    public class FrameAnimationTest extends Activity{
        //當使用java code實現的時,動畫圖片資源陣列
        int[] anims = {R.mipmap.load01
                , R.mipmap.load02
                , R.mipmap.load03
                , R.mipmap.load04
                , R.mipmap.load05
                , R.mipmap.load06};
        //動畫物件
        AnimationDrawable animDrawable;
        //新增動畫的控制元件
        ImageView imgLoad;

        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.anim_frame_load);
            initView();
            addClickListener();
        }

        private void initView() {
            imgLoad = (ImageView) findViewById(R.id.img_load);
        }

        private void addClickListener() {
            //開始逐幀動畫
            findViewById(R.id.tv_load_start).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    statrAnimByJavaCode();
                }
            });
            //結束動畫
            findViewById(R.id.tv_load_stop).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    stopAnim();
                }
            });
        }

        /** java code方式開始動畫*/
        private void statrAnimByJavaCode() {
            if(animDrawable == null){
                animDrawable = new AnimationDrawable();
            }
            for(int source : anims) {
                //新增每幀圖片資源和設定每幀持續時間
                animDrawable.addFrame(getResources().getDrawable(source), 200);
            }
            animDrawable.setOneShot(false);//迴圈播放
            imgLoad.setBackground(animDrawable);
            animDrawable.start();
        }

        /** 結束動畫*/
        private void stopAnim() {
            if(animDrawable != null){
                animDrawable.stop();
            }
        }

        @Override
        protected void onDestroy() {
            super.onDestroy();
            if(animDrawable != null){
                animDrawable = null;
            }
        }
    }

由於我們將AnimationDrawable物件的建立和動畫的啟動,都放在了點選監聽方法onClick裡,所以目前開始動畫之前,介面是空白的,不會顯示動畫的第一幀圖片,如果你有這方面的需求,解決的最快方法就是直接在layout檔案裡給view直接加上background

        <!--這是我們要新增動畫的View-->
        <ImageView
            android:id="@+id/img_load"
            android:layout_width="68dp"
            android:layout_height="68dp"
            android:layout_centerInParent="true"
            android:background="@drawable/anim_frame_load"
            />

五、 總結

好了,到這裡幀動畫的基本使用我們心裡應該都有底了,但是對於原始碼層次的原理剖析,或者幀圖片過大或者幀數量過多等具體情況的優化在這裡都沒有涉及,如果你想好好研究動畫,那麼就去一點點的深入吧。如果想要檢視更多動畫的基礎知識,去我的部落格目錄裡檢視吧,因為關於每塊知識點的介紹,部落格單節寫的比較零散,不容易查詢。

本例原始碼點選下載