動畫矢量圖(簡單幾步就能動起來)

盡管 AnimatedVectorDrawableCompat (自從2016年二月份–Support Library 23.2.0)已經出來有一段時間了,Google官方卻一直沒有提供一份使用教程。你很難搜到相關可靠的文章,也沒有什么能把這個東西完完整整的呈現出來。
所以接下來我嘗試將所有必要知識精簡成你所能理解的東西。
你需要做的事:
1.在你的build.gradle文件中添加AppCompat依賴
compile 'com.android.support:appcompat-v7:25.0.0'
- 我使用了(此時)最新版本 25.0.0 ,但是只要從 23.2.0 開始任何版本可以正常工作
2.創建vector drawable(矢量圖)文件
- 它能被賦予動畫效果
- vector drawable文件必須被放在你項目的res/drawable文件夾
- 更多的相關內容點 這里 (譯注:官方文檔需KX上網)
<?xml version="1.0" encoding="utf-8"?> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportHeight="24" android:viewportWidth="24"> <group android:name="menu" android:pivotX="12" android:pivotY="12"> <group android:name="bottom_container" android:pivotX="20" android:pivotY="17"> <path android:name="bottom" android:pathData="M4,17,L20,17" android:strokeColor="#000" android:strokeLineCap="square" android:strokeLineJoin="miter" android:strokeMiterLimit="10" android:strokeWidth="2"/> </group> <group android:name="stem_container" android:pivotX="12" android:pivotY="12"> <path android:name="stem" android:pathData="M4,12,L20,12" android:strokeColor="#000" android:strokeLineCap="square" android:strokeLineJoin="miter" android:strokeMiterLimit="10" android:strokeWidth="2"/> </group> <group android:name="top_container" android:pivotX="20" android:pivotY="7"> <path android:name="top" android:pathData="M4,7,L20,7" android:strokeColor="#000" android:strokeLineCap="square" android:strokeLineJoin="miter" android:strokeMiterLimit="10" android:strokeWidth="2"/> </group> </group> </vector>
上面的代碼描繪的是一個基礎的黑色菜單(漢堡包)圖標:

3.創建動畫文件
- 它們指定了 vector 的動畫部分
- 可以將多個動畫分別指定給一個 vector drawable的不同的部分
- vector 不同的部分用 name 標簽指定(例如 menu , bottom_container , bottom , stem_container , stem , top_container , top )
- 動畫文件根元素既可以是 set 也可以是 objectAnimator
- 這些文件需要放在res/anim目錄下
接下來的代碼展現了 top_container 動畫,它定義了四個屬性, translateX , translateY , scaleX 以及 rotation :
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:name="top_container"
android:duration="700"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:propertyName="translateX"
android:startOffset="500"
android:valueFrom="0"
android:valueTo="-1.41421356"
android:valueType="floatType"/>
<objectAnimator
android:name="top_container"
android:duration="700"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:propertyName="translateY"
android:startOffset="500"
android:valueFrom="0"
android:valueTo="5"
android:valueType="floatType"/>
<objectAnimator
android:name="top_container"
android:duration="700"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:propertyName="scaleX"
android:startOffset="500"
android:valueFrom="1"
android:valueTo="0.5"
android:valueType="floatType"/>
<objectAnimator
android:name="top_container"
android:duration="700"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:propertyName="rotation"
android:startOffset="500"
android:valueFrom="0"
android:valueTo="45"
android:valueType="floatType"/>
</set>

4.創建animate-vector drawable文件
- animated-vector 將所有的內容都聯系在一起( vector drawable文件和所有的 animation 文件)
- 需要將它放在你項目的res/anim目錄下
<?xml version="1.0" encoding="utf-8"?>
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:drawable="@drawable/vector_menu_back"
tools:ignore="NewApi">
<target
android:name="top_container"
android:animation="@anim/anim_top_container"/>
<target
android:name="stem_container"
android:animation="@anim/anim_stem_container"/>
<target
android:name="bottom_container"
android:animation="@anim/anim_bottom_container"/>
<target
android:name="menu"
android:animation="@anim/anim_menu"/>
</animated-vector>
需要注意的是:
如果你的 minSdkVersion 小于21(如果大于的話,那我真的不知道你為什么會考慮用 AnimatedVectorDrawableCompat …正常用 AnimatedVectorDrawable 就行了),Android Studio可能會在你的 animated-vector 文件中彈出一個靜態檢查警告:

不要擔心這個警告!如果你的代碼沒有錯誤,你的 AnimatedVectorDrawableCompat 會忽略掉它并且能夠正常工作。當然如果你不想再看到警告,可以添加 tools:ignore="NewApi" :

5.編輯你的build.gradle文件
- 在你的 build.gradle 文件中,將 vectorDrawables.useSupportLibrary = true 添加進 android 部分的 defaultConfig 內
- 你需要這行代碼,這樣你的 animated-vector 才能兼容API小于 Lollipop版本的系統
android {
compileSdkVersion 24
buildToolsVersion "24.0.3"
defaultConfig {
applicationId "com.junyuan.wukongnew"
minSdkVersion 21
targetSdkVersion 24
versionCode 1
versionName "1.0"
vectorDrawables.useSupportLibrary = true
}
...
}
6.將你的AnimatedVectorDrawableCompat設置到ImageView或者ImageButton
- 你可以用 app:srcCompat 把它添加進xml文件
<ImageView
android:id="@+id/iv_animated"
android:layout_width="48dp"
android:layout_height="48dp"
app:srcCompat="@drawable/animated_vector_menu_back"/>
- 或者通過java代碼:
final AnimatedVectorDrawableCompat avd = AnimatedVectorDrawableCompat.create(this, R.drawable.animated_vector_menu_back);
animatedIv.setImageDrawable(avd);
7.在你需要的時候開啟動畫
- 獲得 AnimatedVectorDrawableCompat 的引用(或者是它的一個實現類– Animatable ),如果你的 AnimatedVectorDrawableCompat 是通過java代碼添加的,可以直接使用這個對象的引用(你可以跳過這步):
final Animatable animatable = (Animatable) animatedIv.getDrawable();
- 開啟動畫
animatable.start()

好消息和壞消息
讓我們先來聽聽好消息:
你可以很輕松通過 Roman Nurik 的AndroidIconAnimator這個工具(盡管當前它是預覽版,但是也足夠有用了)實現步驟1-3。它可以將svg文件和你所指定的動畫元素轉換成 animated-vector drawable文件
有一件很有意思的事情是導出來的來的 animated-vector 文件使用了 aapt 工具的一些非常厲害的功能,導出來的drawable文件包含了全部動畫所需的代碼(包括 vector drawable和 animation 文件)。就是將步驟1-3的所有文件都包含在一個文件里。
壞消息來了:
AnimatedVectorDrawableCompat 在API小于21時有一些限制:
Chris Banes 的 文章 中指出:
animate vectors 在API小于21的平臺上工作時同樣有一些限制,當前在這些平臺上有一下這幾點限制:
路徑繪制(PathType evaluator),這被用來從一個路徑繪制到另一個路徑
路徑插值器,這被用來定義一個靈活的插值器(展現成一個路徑)以代替系統自動生成的,比如說線性插值器(LinearInterpolator)
按路徑移動,這很少能用到,幾何圖形能在限制路徑上來回運動
大致意思就是你可以忘了 pathData 元素的動畫 pathData ,我們只能期望谷歌的天才們能研究一個方法將這個功能兼容到低版本的系統上去。
來自:https://besttao.github.io/2016/11/30/[譯]動畫矢量圖(簡單幾步就能動起來)/