Android中具有動畫效果的圖片資源
在一些場景下,圖片需要具有動畫效果。當你想顯示一個由多張圖片組成的loading動畫,或者一個圖示切換過程,就需要到具有動畫效果的圖片了。Android提供了幾種方式實現動畫圖片。
下面的是個示例:
第一種方式是使用Animation Drawable,這是通過建立多張靜態圖片構成動畫的方式,類似動畫片和gif。第二種方式是使用Animated Vector Drawable,然後改變其屬性。
使用AnimationDrawable
當你可以定義動畫中的每一幀時,可以使用AnimationDrawable,AnimationDrawable和ShapeDrawable等一樣,都可以通過xml進行編寫,然後設定給ImageView。
舉個栗子:
在res/drawable目錄下建立一個drawable檔案,內容如下:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true">
<item
android:drawable="@drawable/signal_wifi_1_bar"
android:duration ="200"/>
<item
android:drawable="@drawable/signal_wifi_2_bar"
android:duration="200"/>
<item
android:drawable="@drawable/signal_wifi_3_bar"
android:duration="200"/>
<item
android:drawable="@drawable/signal_wifi_4_bar"
android:duration ="200"/>
</animation-list>
其中每個item表示一幀,duration表示該幀持續時間,oneshot=true表示每一幀播放完後不迴圈播放了,停留在最後一幀。程式碼如下:
class AnimationDrawableActivity : AppCompatActivity() {
private lateinit var wifiSignalAnimation: AnimationDrawable
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_animation_drawable)
findViewById<ImageView>(R.id.iv_wifi_signal).apply {
setBackgroundResource(R.drawable.wifi_signal)
wifiSignalAnimation = background as AnimationDrawable
}
}
override fun onStart() {
super.onStart()
wifiSignalAnimation.start()
}
}
在onStart()方法中呼叫start()方法是因為在onCreate()方法中ImageView還沒有新增到Window中。下面是oneshot=false的gif圖。
由於AnimationDrawable是多張靜態圖片的集合,因此需要注意OOM問題。上面的例子是一個尋找wifi訊號的動畫,時間設的有點短,所以動畫效果很快。
使用AnimatedVectorDrawable
AnimatedVectorDrawable(AnimatedVectorDrawableCompat)允許你改變向量圖片的屬性,比如旋轉或改變path資料以改變形狀。
你通常需要在三個地方定義xml檔案:
- 在res/drawable目錄下定義向量圖片,使用元素
- 在res/drawable目錄下定義向量動畫圖片,使用元素
- 在res/animator目錄下定義一個或多個物件動畫,使用元素
向量動畫圖片可以更改和
舉個例子:
<!-- res/drawable/vectordrawable.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportHeight="600"
android:viewportWidth="600">
<group
android:name="rotationGroup"
android:pivotX="300.0"
android:pivotY="300.0"
android:rotation="45.0">
<path
android:name="v"
android:fillColor="#000000"
android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z"/>
</group>
</vector>
向量動畫圖片給drawable中指定的名稱指定動畫:
<!-- res/drawable/animvectordrawable.xml -->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/vectordrawable">
<target
android:name="rotationGroup"
android:animation="@animator/rotation"/>
<target
android:name="v"
android:animation="@animator/path_morph"/>
</animated-vector>
上面的例子中給rotationGroup和分別指定了動畫,接下來是定義這兩個動畫,
<!-- res/animator/rotation.xml -->
<objectAnimator
android:duration="6000"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360" />
<!-- res/animator/path_morph.xml -->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="3000"
android:propertyName="pathData"
android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z"
android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z"
android:valueType="pathType" />
</set>
程式碼如下,和AnimationDrawable類似:
class AnimationDrawableActivity : AppCompatActivity() {
private lateinit var vectorAnimation: AnimatedVectorDrawable
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_animation_drawable)
findViewById<ImageView>(R.id.iv_wifi_signal).apply {
setBackgroundResource(R.drawable.animvectordrawable)
vectorAnimation = background as AnimatedVectorDrawable
}
findViewById<Button>(R.id.btn_start).setOnClickListener {
vectorAnimation.start()
}
}
}
執行結果如下:
這邊加了一個按鈕進行控制,不然gif不好錄,尷尬…
這邊是將向量動畫圖片的檔案分成了三個檔案,其實也可以將其融合到一個檔案中去,
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
xmlns:android="http://schemas.android.com/apk/res/android">
<aapt:attr name="android:drawable">
<vector
android:width="200dp"
android:height="200dp"
android:viewportHeight="600"
android:viewportWidth="600">
<group
android:name="rotationGroup"
android:pivotX="300.0"
android:pivotY="300.0"
android:rotation="45.0">
<path
android:name="v"
android:fillColor="#000000"
android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z"/>
</group>
</vector>
</aapt:attr>
<target android:name="rotationGroup">*
<aapt:attr name="android:animation">
<objectAnimator
android:duration="6000"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360"/>
</aapt:attr>
</target>
<target android:name="v">
<aapt:attr name="android:animation">
<set>
<objectAnimator
android:duration="3000"
android:propertyName="pathData"
android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z"
android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z"
android:valueType="pathType"/>
</set>
</aapt:attr>
</target>
</animated-vector>
總結
本文主要翻譯自https://developer.android.com/guide/topics/graphics/drawable-animation