Android SVG矢量資源的使用方法

VectorDrawable 與 SVG

Android 5.0(Lollipop, API 21)後,新增了<vector>標籤,以VectorDrawable的形式支持SVG類型矢量圖形(SVG本質爲XML標記描述的圖形)。
※ Android不直接支持SVG圖形文件

SVG文件(XML)對應的VectorDrawable資源封裝格式爲:

 <vector xmlns:andro
     android:height="64dp"
     android:width="64dp"
     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>

※ 通常由SVG文件轉換爲VectorDrawable,而非手工錄入

  1. <vector> 是 VectorDrawable 對應的根標籤
  2. android:widthandroid:height對應矢量圖的實際參考尺寸(實際可根據容器尺寸無損縮放,但此值將作爲容器(ImageView)的 wrap_content 參考尺寸),基於加載性能考慮,Google推薦限定在 200x200dp 以內,一般與下面的viewportWidthviewportHeight成比例定義
  3. android:viewportWidthandroid:viewportHeight是指當前Drawable對應的Canvas的大小,用於爲<path/>標籤中的路徑數據提供繪製位置的參考座標系及繪製範圍
  4. <path/>標籤對應路徑信息, 這裏的path與我們自定義繪製圖形時用的Path原理一樣, 就是記錄一些繪圖操作, 具體對應其中的 pathData。
  5. android:fillColor爲默認黑色(#FF000000)時,在View容器內將使用tint顏色取代,否則將呈現爲android:fillColortint的混合顏色。

<path/>路徑的路徑描述指令含義表:

M = moveto 相當於 android Path 裏的moveTo(),用於移動起始點 
L = lineto 相當於 android Path 裏的lineTo(),用於畫線 
H = horizontal lineto 用於畫水平線 
V = vertical lineto 用於畫豎直線 
C = curveto 相當於cubicTo(),三次貝塞爾曲線 
S = smooth curveto 同樣三次貝塞爾曲線,更平滑 
Q = quadratic Belzier curve quadTo(),二次貝塞爾曲線 
T = smooth quadratic Belzier curveto 同樣二次貝塞爾曲線,更平滑 
A = elliptical Arc 相當於arcTo(),用於畫弧 
Z = closepath 相當於closeTo(),關閉path

大寫代表絕對位置, 小寫代表相對位置

官方標準定義細則參考:SVG Paths Definition - W3C

SVG圖標平臺

【Iconfont】阿里媽媽矢量圖標平臺

SVG編輯軟件

Inkscape
跨平臺開源矢量圖形編輯軟件,免費 + 三平臺通用,支持直接編輯XML數據
類似的軟件還有Illustrator、CorelDraw等


SVG 轉 VectorDrawable

  • 使用 Vector Asset Studio 轉換,在res目錄右鍵菜單上選擇 New > Vector Asset
  • 通過開源項目 svg2android 在線轉換

※ 初始化VectorDrawable將消耗更多CPU資源,Google推薦將矢量圖最大尺寸限定在 200x200dp 以內


VectorDrawable 向後兼容

對於Android 5.0之前的設備,有兩種方式兼容VectorDrawable資源:

1. 利用 Vector Asset Studio 工具動態生成位圖

Android Studio 內置一個名爲 Vector Asset Studio 的工具,在低版本SDK上編譯APK期間,針對VectorDrawable腳本自動生成一組PNG位圖資源BitmapDrawable,取代矢量圖形(在5.0及以後的手機上運行時會正常引用VectorDrawable)。

需要配置build.gradle

defaultConfig {
    vectorDrawables.generatedDensities = ['hdpi','xxhdpi']
}

※ 自動生成PNG時,所支持的VectorDrawable元素子集

2. 添加 Support Library 23.2+ 兼容包

Support Library 23.2+ 包中包含VectorDrawableCompatAnimatedVectorDrawableCompat兼容類,用於代碼中橋接爲BitmapDrawable及其動畫支持,其中Drawable最低SDK爲Android 2.1,動畫最低SDK爲Android 3.0

※ 兼容包要求使用Gradle 2.0或以上版本,並且不支持VectorDrawable嵌套引用,不支持直接解析爲VectorDrawable類型,也不再編譯期生成PNG位圖

build.gradle配置如下:

android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

dependencies {
  compile 'com.android.support:appcompat-v7:23.2.0'
}

兼容包在矢量資源引用、代碼調用時,存在一定限制

  • 在 ImageView 等引用 VectorDrawable 資源時,需要使用app:srcCompat取代android:src
  • 代碼中使用setImageResource()指定資源 id 時,無需更改代碼
  • 將 VectorDrawable 用於 View 背景時,需要通過以下代碼設定:
Resources resources = context.getResources(Resources, int, Theme);
Theme theme = context.getTheme();
Drawable drawable = VectorDrawableCompat.create(resources, R.drawable.vector_drawable, theme);
view.setBackground(drawable);

代碼中需要進行Drawable的實現類型轉換時,可使用以下代碼段執行:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
   VectorDrawable vectorDrawable =  (VectorDrawable) drawable;
} else {
   BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
}

矢量動畫

使用矢量圖可進行特殊的動畫繪製,如形態變換、動態繪圖等。

主要步驟

定義矢量資源及其關聯動畫 XML 腳本

  1. 創建矢量圖形資源VectorDrawable,並在需要動畫特效的子元素上使用屬性android:name給定任意動畫對象名
  2. 創建Animator屬性動畫腳本,可使用ObjectAnimatorAnimatorSet,對VectorDrawable的特定元素屬性進行動畫控制
  3. 創建AnimatedVectorDrawable,作用是連接VectorDrawableAnimator,組合爲單一動畫型Drawable對象
  4. 創建好的AnimatedVectorDrawable不能直接用於 ImageView,需要通過代碼設定,並顯式開始執行動畫
官方文檔
  • XML腳本具體定義方式可參考 開發手冊 AnimatedVectorDrawable
  • 開發手冊 內聯複合XML資源 提供了通過 AAPT 系統插件,實現單一XML腳本混合定義的方式,需要聲明命名空間 xmlns:aapt="http://schemas.android.com/aapt"

在線實時輸出 XML 腳本

Google工程師開發的開源項目 AndroidIconAnimator,可實現在線實時構造、編輯、預覽 VectorDrawable 動畫,並導出XML腳本,使用教程可參考 Qiita帖子

代碼設置

創建好的 VectorDrawable 動畫資源,需要通過代碼方式加載到 View 容器內,並指定執行動畫

使用原生支持的代碼設定(5.0 LOLLIPOP, API 21)

ImageView imageView = (ImageView) findViewById(R.id.imageView);
AnimatedVectorDrawable vectorDrawable = (AnimatedVectorDrawable) getResources().getDrawable(AnimatedVectorDrawableRes, Theme);
imageView.setImageDrawable(vectorDrawable);
vectorDrawable.start();

使用 Support Library 時的動畫設置

矢量動畫要求最低SDK爲Android 3.0,並且不支持<path>路徑類型的變換

ImageView imageView = (ImageView) findViewById(R.id.imageView);
AnimatedVectorDrawableCompat drawableCompat = AnimatedVectorDrawableCompat.create(context, AnimatedVectorDrawableRes);
imageView.setImageDrawable(drawableCompat);
drawableCompat.start();
  • 可執行的特有動畫效果,可參考 VectorDrawable 元素屬性列表
  • 所有屬性中文解釋可參考 Android矢量圖形與矢量動畫
  • 其中一種動效實例,可參考博文 Android使用SVG矢量動畫

特別介紹幾個特殊屬性:

  • <group>元素:
    • rotation:旋轉角度,取值爲360角度,valueType=floatType
    • pivotX / pivotY:旋轉中心座標,以viewport爲參照基準
  • <path>元素:
    • pathData:矢量圖形的繪製路徑數據位點,可動畫形變爲另一種圖案,要求動畫參數值必須擁有相同長度參數及一致的路徑描述指令,並且 ObjectAnimator 中android:valueType="pathType"(Support 包不支持該數據進行變換動畫)
    • trimPathStart:從路徑起始點開始向後裁剪(擦除)的相對距離,取值 [0, 1],,0 表示路徑起始點,1 表示路徑結束點,可實現逐步消退、繪製動效,android:valueType="floatType"
    • trimPathEnd:從路徑結束點開始向前裁剪的相對距離,取值 [0, 1],0 表示路徑起始點,1 表示路徑結束點
    • trimPathOffset:從路徑起始、結束點開始裁剪的相對距離,取值 [0, 1],0 表示不裁剪,1 表示該路徑完全不繪製
  • <clip-path>元素:遮罩路徑、反蒙版路徑,該路徑範圍內的元素纔會真正進行繪製,作用於當前所在的<group>內定義在其後面的所有<path>元素
    • pathData:定義遮罩路徑,動畫操作方式與<path>相同

pathData 形變動畫參考

  • 理解Android VectorDrawable中的pathData命令
  • PathMorphing with AnimatedVectorDrawables in Android
  • 【VectAlign】pathData自動算法變換對齊工具

已知bug:

  • <animated-vector>標籤在使用時會發生錯誤警告requires API level 21,不影響兼容包的編譯運行
  • 放置於animator目錄內的Animator腳本,需要在<animated-vector><target>中手工引用@animator/資源id(自動提示補全菜單失效)
  • 使用動畫時,ImageView 不能使用android:tint屬性,否則會導致Mutate() is not supported for older platform異常崩潰
  • 通過 AAPT 標籤使用單一腳本混合定義時,Android Studio 會出現識別錯誤提示
  • 矢量動畫通過關聯 Property Animation 打包爲 Drawable 方式實現,對屬性的動態修改將影響所有同一 Drawable 資源產生的對象(Drawable 狀態共享機制),並且兼容包不支持 mutate() 調用(狀態分離,兼容包內要求API 23以上),實際上代碼暫時無法訪問矢量元素內部屬性(如 pathData 等)

其他參考文獻及工具鏈接集合:

  • VectorDrawable
  • Iconfont 矢量圖標平臺
  • AndroidIconAnimator 矢量動畫XML生成器
  • VectAlign pathData自動對齊工具
  • Android的矢量圖支持 - VectorDrawable
  • Android中使用SVG矢量圖

首發地址在 簡書 上

發佈了55 篇原創文章 · 獲贊 25 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章