VectorDrawable 詳解

jopen 8年前發布 | 9K 次閱讀 安卓開發 Android開發 移動開發

Android 5.0系統中引入了 VectorDrawable 來支持矢量圖(SVG),同時還引入了 AnimatedVectorDrawable 來支持矢量圖動畫。但是一年半過去了,使用矢量圖的應用還是比較少,主要原因之一是兼容性問題,在 5.0 之前的版本上還是要使用 png 或者 jpg 圖片。現在 隨著 Android Studio 和 Gradle plugin 的功能進一步完善,已經可以大部分情況下滿足兼容性的需求了。所以是時候使用 矢量圖 了。 本文就來詳解下 Android 中對矢量圖的支持。

SVG 和 VectorDrawable 的基本知識

VectorDrawable 并沒有支持所有的 SVG 規范,目前只支持 PathData 和有限的 Group 功能。另外還有一個 clip-path 屬性來支持后面繪圖的區域。 所以對于使用 VectorDrawable 而言,我們只需要了解 SVG 的 PathData 規范即可。通過查看 PathData 文檔,可以看到 path 數據包含了一些繪圖命令,比如 :

* moveto 命令 M or m ,移動到新的位置 (大寫的命令為絕對坐標命令;小寫的命令為相對坐標命令, 下同)

* closepath 命令 Z or z,封閉路徑,從當前的位置畫一條直線到該路徑或者子路徑起始位置

* lineto 命令 L or l,從當前的位置畫一條線到指定的位置

* horizontal lineto 命令 H or h,水平畫一條直線到指定位置

* vertical lineto 命令 V or v,垂直畫一條直線到指定位置

* … 還有很多其他命令,詳情請參考文檔

在 文檔中有個繪制三角形的示例:

XHTML

<svg width="4cm" height="4cm" viewBox="0 0 400 400"
     xmlns="http://www.w3.org/2000/svg" version="1.1">
  <rect x="1" y="1" width="398" height="398"
        fill="none" stroke="blue" />
  <path d="M 100 100 L 300 100 L 200 300 z"
        fill="red" stroke="blue" stroke-width="3" />
</svg>
<svgwidth="4cm" height="4cm" viewBox="0 0 400 400"
    xmlns="http://www.w3.org/2000/svg" version="1.1">
  <rectx="1" y="1" width="398" height="398"
        fill="none" stroke="blue"/>
  <pathd="M 100 100 L 300 100 L 200 300 z"
        fill="red" stroke="blue" stroke-width="3"/>
</svg>

該示例的畫布大小為 400 X 400像素(左上角坐標為0,0; 右下角坐標為400,400), path 路徑為: 移動到 100、100 位置,然后畫一條線到絕對坐標 300、100位置,然后畫一條線到絕對坐標 200、300位置,然后畫一條線到該路徑的起始位置。這樣一個倒三角形就繪制出來了。

只需要把上面的 path 路徑中的數據放到 VectorDrawable 定義xml文件中,就可以實現一個 Android 版本的 矢量圖了。例如 在 drawable 目錄中創建一個 triangle.xml 文件,內容如下:

XHTML

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="400dp"
    android:height="400dp"
    android:viewportHeight="400"
    android:viewportWidth="400">
    <path
        android:pathData="M 100 100 L 300 100 L 200 300 z"
        android:strokeColor="#000000"
        android:strokeWidth="5"
        android:fillColor="#FF0000"
        />
</vector>
<?xmlversion="1.0" encoding="utf-8"?>
<vectorxmlns:android="http://schemas.android.com/apk/res/android"
    android:width="400dp"
    android:height="400dp"
    android:viewportHeight="400"
    android:viewportWidth="400">
    <path
        android:pathData="M 100 100 L 300 100 L 200 300 z"
        android:strokeColor="#000000"
        android:strokeWidth="5"
        android:fillColor="#FF0000"
        />
</vector>

需要注意的是, 在根元素 vector 上有兩個寬高設置,其中 viewport 是指矢量圖里面的畫布大小,而android:width 和 android:height 是指該矢量圖所對應的 VectorDrawable 的大小。

path 元素里面的 pathData 就是矢量圖的路徑數據,除此之外還可以設置其他屬性。 path 元素一共包含如下屬性:

  • android:name 定義該 path 的名字,這樣在其他地方可以通過名字來引用這個路徑
  • android:pathData 和 SVG 中 d 元素一樣的路徑信息。
  • android:fillColor 定義填充路徑的顏色,如果沒有定義則不填充路徑
  • android:strokeColor 定義如何繪制路徑邊框,如果沒有定義則不顯示邊框
  • android:strokeWidth 定義路徑邊框的粗細尺寸
  • android:strokeAlpha 定義路徑邊框的透明度
  • android:fillAlpha 定義填充路徑顏色的透明度
  • android:trimPathStart 從路徑起始位置截斷路徑的比率,取值范圍從 0 到1
  • android:trimPathEnd 從路徑結束位置截斷路徑的比率,取值范圍從 0 到1
  • android:trimPathOffset 設置路徑截取的范圍 Shift trim region (allows showed region to include the start and end), in the range from 0 to 1.
  • android:strokeLineCap 設置路徑線帽的形狀,取值為 butt, round, square.
  • android:strokeLineJoin 設置路徑交界處的連接方式,取值為 miter,round,bevel.
  • android:strokeMiterLimit 設置斜角的上限,Sets the Miter limit for a stroked path. 注: 當strokeLineJoin設置為 “miter” 的時候, 繪制兩條線段以銳角相交的時候,所得的斜面可能相當長。當斜面太長,就會變得不協調。strokeMiterLimit 屬性為斜面的長度設置一個上限。這個屬性表示斜面長度和線條長度的比值。默認是 10,意味著一個斜面的長度不應該超過線條寬度的 10 倍。如果斜面達到這個長度,它就變成斜角了。當 strokeLineJoin 為 “round” 或 “bevel” 的時候,這個屬性無效。

根元素 vector 是用來定義這個矢量圖的,該元素包含如下屬性:

  • android:name 定義該drawable的名字
  • android:width 定義該 drawable 的內部(intrinsic)寬度,支持所有 Android 系統支持的尺寸,通常使用 dp
  • android:height 定義該 drawable 的內部(intrinsic)高度,支持所有 Android 系統支持的尺寸,通常使用 dp
  • android:viewportWidth 定義矢量圖視圖的寬度,視圖就是矢量圖 path 路徑數據所繪制的虛擬畫布
  • android:viewportHeight 定義矢量圖視圖的高度,視圖就是矢量圖 path 路徑數據所繪制的虛擬畫布
  • android:tint 定義該 drawable 的 tint 顏色。默認是沒有 tint 顏色的
  • android:tintMode 定義 tint 顏色的 Porter-Duff blending 模式,默認值為 src_in
  • android:autoMirrored 設置當系統為 RTL (right-to-left) 布局的時候,是否自動鏡像該圖片。比如 阿拉伯語。
  • android:alpha 該圖片的透明度屬性

有時候我們需要對幾個路徑一起處理,這樣就可以使用 group 元素來把多個 path 放到一起。 group 支持的屬性如下:

  • android:name 定義 group 的名字
  • android:rotation 定義該 group 的路徑旋轉多少度
  • android:pivotX 定義縮放和旋轉該 group 時候的 X 參考點。該值相對于 vector 的 viewport 值來指定的。
  • android:pivotY 定義縮放和旋轉該 group 時候的 Y 參考點。該值相對于 vector 的 viewport 值來指定的。
  • android:scaleX 定義 X 軸的縮放倍數
  • android:scaleY 定義 Y 軸的縮放倍數
  • android:translateX 定義移動 X 軸的位移。相對于 vector 的 viewport 值來指定的。
  • android:translateY 定義移動 Y 軸的位移。相對于 vector 的 viewport 值來指定的。

通過上面的屬性可以看出, group 主要是用來設置路徑做動畫的關鍵屬性的。

最后, vector 還支持 clip-path 元素。定義當前繪制的剪切路徑。注意,clip-path 只對當前的 group 和子 group 有效。

  • android:name 定義 clip path 的名字
  • android:pathData 和 android:pathData 的取值一樣。

從上面 vector 支持的屬性可以看出,功能還是比較豐富的。例如 前面提到的三角形,通過 group 可以把其旋轉 90度。

XHTML

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="400dp"
    android:height="400dp"
    android:viewportHeight="400"
    android:viewportWidth="400">
    <group
        android:name="name"
        android:pivotX="200"
        android:pivotY="200"
        android:rotation="90">
        <path
            android:fillColor="#FF0000"
            android:pathData="M 100 100 L 300 100 L 200 300 z"
            android:strokeColor="#000000"
            android:strokeWidth="5" />
    </group>
</vector>
<?xmlversion="1.0" encoding="utf-8"?>
<vectorxmlns:android="http://schemas.android.com/apk/res/android"
    android:width="400dp"
    android:height="400dp"
    android:viewportHeight="400"
    android:viewportWidth="400">
    <group
        android:name="name"
        android:pivotX="200"
        android:pivotY="200"
        android:rotation="90">
        <path
            android:fillColor="#FF0000"
            android:pathData="M 100 100 L 300 100 L 200 300 z"
            android:strokeColor="#000000"
            android:strokeWidth="5"/>
    </group>
</vector>

來自: http://blog.chengyunfeng.com/?p=834

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!