Android 幀動畫使用

幀動畫

使用一系列不同的圖片,然後像一卷膠捲一樣按順序播放,這是一種傳統的動畫,也可稱為幀動畫。也可以比喻為像一卷膠捲一樣按順序播放。
播放起來,有點像在看gif圖。

本文介紹使用AnimationDrawable類來實現動畫效果。
為了開發方便,我們可以在xml中指定動畫各個幀的信息。

使用背景圖片

這是第一個例子。我們先準備4張圖片(圖片請自備)放進res/drawable/中。
在這個目錄里,再新建一個文件ani_frame_1.xml

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="//schemas.android.com/apk/res/android"
    android:id="@+id/ani_frame_1"
    android:oneshot="false">
    <item
        android:drawable="@drawable/f_zan_1"
        android:duration="250" />
    <item
        android:drawable="@drawable/f_zan_4"
        android:duration="250" />
    <item
        android:drawable="@drawable/f_zan_3"
        android:duration="250" />
    <item
        android:drawable="@drawable/f_zan_2"
        android:duration="250" />
</animation-list>

可以看到根節點<animation-list>包含了4個item。每個子節點都定義了一個幀。
duration是這一幀的時常(毫秒)。drawable是指定可繪製資源。oneshot="false",表示讓動畫一直循環播放下去。
這樣動畫資源就準備好了。

在layout中準備一個ImageView,用它來顯示動畫

<ImageView
    android:id="@+id/iv1"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:layout_marginTop="60dp" />

在activity中操作這個ImageView。把動畫資源設置為背景。

var mFrameIv: ImageView? = null
// override fun onCreate(savedInstanceState: Bundle?)
mFrameIv = findViewById(R.id.iv1)
mFrameIv!!.setBackgroundResource(R.drawable.ani_frame_1)

把ImageView的背景強轉為AnimationDrawable。播放動畫,要用AnimationDrawable.start()方法。

val ani: AnimationDrawable = mFrameIv!!.background as AnimationDrawable
ani.start()

當動畫正在播放時,調用start()方法是不會影響當前播放的。

停止動畫,AnimationDrawable.stop()

val ani: AnimationDrawable = mFrameIv!!.background as AnimationDrawable
ani.stop()

stop()方法可以讓動畫停止在當前幀。再調用start()的話,會從頭開始播放。

使用src

前面我們利用的是ImageView的背景資源。我們也可以使用src
準備另一個動畫資源ani_frame_2

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="//schemas.android.com/apk/res/android"
    android:id="@+id/ani_frame_1"
    android:oneshot="true">
    <item
        android:drawable="@drawable/f_zan_1"
        android:duration="250" />
    <item
        android:drawable="@drawable/f_zan_4"
        android:duration="250" />
    <item
        android:drawable="@drawable/f_zan_3"
        android:duration="250" />
    <item
        android:drawable="@drawable/f_zan_2"
        android:duration="250" />
</animation-list>

android:oneshot="true",動畫播放1次後就會自行停止並保持在最後一幀。

! 注意,停止後並不是回到第一幀。

然後在layout中,把它設置為ImageView的src

<ImageView
    android:id="@+id/iv1"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:layout_marginTop="60dp"
    android:src="@drawable/ani_frame_2" />

在activity中就不是操作ImageView的background了,而是操作drawable

// 啟動
val ani: AnimationDrawable = frameIv.drawable as AnimationDrawable
ani.start()

// 停止
val ani: AnimationDrawable = frameIv.drawable as AnimationDrawable
ani.stop()

可以看到,2個例子中都需要操作AnimationDrawable
請務必注意,對 AnimationDrawable.start() 方法不能在 Activity 的 onCreate() 方法期間調用,因為 AnimationDrawable 尚未完全附加到窗口。如果想立即播放動畫而無需互動,那麼可能需要從 Activity 中的 onStart() 方法進行調用,該方法會在 Android 在屏幕上呈現視圖時調用。

AnimationDrawable類有幾個屬性可以注意一下

屬性 說明
isOneShot 是否只播放1次,與xml中的android:oneshot對應
isRunning 當前動畫是否正在播放
numberOfFrames 幀的數量

參考