Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android動畫總結系列(6)——矢量圖形與矢量動畫

Android動畫總結系列(6)——矢量圖形與矢量動畫

編輯:關於Android編程

按照我一開始的打算,上面一篇文章應該是“Android動畫總結系列(5)——屬性動畫源碼分析”,不過屬性動畫源碼分析寫起來還比較復雜,因為某些原因,我把精力投入到矢量動畫這塊了,第5篇估計會在後面一兩周寫完。本篇文章,我寫的是Android5.0引入的新動畫效果——矢量動畫,初步打算後面還會加一篇源碼分析。

 

一、概述

 

1.1 簡述

Android應用的不斷發展帶來了安裝包過大的尴尬,而Android之前一直都不支持矢量圖形,是引起尴尬的一個重要原因。其實Android繪制界面時也是通過各種類似矢量圖形命令操作完成的,所以Android最終在Lolliop引入矢量圖形既是大勢所趨,也是水到渠成的一件事情。矢量圖有很多標准,Android支持的是SVG標准(可縮放矢量圖形Scalable Vector Graphics)。但不是全量支持,准確的說Android支持的是SVG標准中Path相關的部分。

SVG是通用的矢量圖標准,我們可以很輕易的從Photoshop之類的軟件導出想要的圖形。導出的文件後綴是*.svg,這個文件的內容是文本格式的,用txt文件查看就可以打開,其內部是一系列遵循SVG規范的命令列表。

 

SVG Path的路徑是一系列的命令組成的,每條命令告訴繪圖系統,如何繪制路徑。命令的寫法:

1)每條命令之間可以用換行/空格/逗號進行分隔;

2)每條命令內的命令和其參數之間可以用換行/空格/逗號分隔,也可以直接連在一起;

3)命令的各個參數間可以用換行/空格/逗號分隔;

通常如果路徑過長,為便於閱讀,建議命令之間用換行,命令與參數之間用空格,參數之間用逗號進行分隔。

 

1.2 Path命令定義與用法

Android支持的路徑命令包括:

M: move to 移動到繪制點

用法:M X,Y (X,Y)是Canvas上的點的位置,M命令會改變Path的初始點 ,如M 10,10或者 M10 10,Path從(10,10)開始繪制。

對應android.graphics.Path的void moveTo(float x, float y)方法。

 

L:line to 繪制直線

用法:1)L X,Y 從當前位置繪制直線到(X,Y),如L 10,10或者L10 10

2)對於水平方向和垂直方向繪制直線的時候,L命令有兩個簡化表達法,H X表示水平連接,V Y表示垂直連接,比如M 10,10H12表示的是從(10,10)繪制一條直線到(12,10),M10,10V12表示從(10,10)繪制一條直線到(10,12)。

對應Path類void lineTo(float x, float y)方法。

 

Z:close 閉合,沒有參數,表示用直線連接Path的初始點和Path的終點。

用法:一般Z命令用在一條Path的最末尾,但其實在Z命令後還可以再繼續新的路徑,不過Z命令不改變Path的初始點,所以M2,2L5,5L5,10ZL6,4L7,3Z命令第二個Z認為的Path初始點還是(2,2),如果是M2,2L5,5L5,10ZM3,2L6,4L7,3Z命令,則第二個Z認為的Path起始點是(3,2)。

對應Path類的void close()方法。

 

C:cubic bezier 繪制三次貝塞爾曲線

用法:C X1,Y1 X2,Y2 X,Y 從當前點到(X,Y)點繪制一條控制點是(X1,Y1)、(X2,Y2)的三次貝塞爾曲線,如C 6,4, 7,4, 10,5,控制點是(6,4)、(7,4),最終點是(10,5)。

對應Path類的void cubicTo(float x1, float y1, float x2, float y2,float x3, float y3)方法,方法參數與上面定義順序完全相同。

 

Q:quatratic bezier 二次貝塞爾曲線

用法:Q x1,y1 x,y,從當前點到(x,y)繪制一條控制點是(x1,y1)的二次貝塞爾曲線,如Q 6,4 10,5,控制點是(6,4),最終點是(10,5)。

對應Path類的void quadTo(float x1, float y1, float x2, float y2)方法,參數定義與順序同上。

 

A:ellipse 繪制一個橢圓圓弧

用法:繪制橢圓圓弧的參數比較復雜,如下:A rx ry x-axis-rotation large-arc-flag sweep-flag X Y,表示繪制一個橢圓圓弧經過(X,Y)點。

rx:橢圓橫軸半徑

ry:橢圓豎軸半徑

x-axis-rotation:橢圓橫軸相對於CanvasX軸的偏移角度

large-arc-flag:在前面三個參數確定的情況下,滿足當前點到指定點(X,Y)位置條件的圓弧總是有四條,此值取0表示繪制小弧度,取值1表示繪制大弧度

sweep-flag:在前面三個參數確定的情況下,滿足當前點到指定點(X,Y)位置條件的圓弧總是有四條,去掉上面large-arc-flag標識後還有兩個,sweep-flag 取值0表示繪制逆時針方向的圓弧,取值1表示繪制順時針方向的圓弧。

盜個圖來輔助表達:

\

舉例:M5,5,A 3,2 0 1 1 5 5.00001 此命令基本上繪制了一個完整的橢圓。注意如果寫成M5,5,A 3,2 0 1 1 5 5就什麼都展示不了了,因為兩點完全相等,命令的目標連接兩點已經達到,就不繞大彎子了,所以此處或者目標X或者目標Y要做一點細微的區別。

此命令對應的是void arcTo(float left, float top, float right, float bottom, float startAngle,float sweepAngle, boolean forceMoveTo),不過參數需要做轉化。

 

這裡列出的每個命令還有對應的小寫形式,上面的大寫字母代表後面的參數是絕對坐標,而小寫字母表示相對坐標。

假如當前繪圖位置是X0,Y0,則:

M x, y 對應的是 m x-X0, y-Y0;小寫形式對應的是Path類的void rMoveTo(float dx, float dy)。

L x, y 對應的是 l x-X0, y-Y0;小寫形式對應的是Path類的void rLineTo(float dx, float dy)。

Z 對應的是z,兩者作用相同;大小寫形式對應的都是Path類的void close()。

C x1,y1 x2,y2 x,y 對應的是 c x1-X0, y1-Y0, x2-X0, y2-Y0 x-X0, y-Y0;小寫形式對應的是 Path類的void rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3)。

Q x1,y1 x,y 對應的是 q x1-X0, y1-Y0 x-X0,y-Y0;小寫形式對應的是Path類的rQuadTo( float dx1, float dy1, float dx2, float dy2)。

A rx ry x-axis-rotation large-arc-flag sweep-flag x y 對應的是A rx ry x-axis-rotation large-arc-flag sweep-flag x-X0 y-Y0,小寫形式在Path類中與大寫方式對應接口的相同,都需要做參數轉化。

 

1.3 SVG與Android XML的轉化

http://inloop.github.io/svg2android/提供了將SVG轉化為android的XML文件的在線工具。

不過要注意一點,因為Android不完全支持SVG標准,所以svg2android的項目會丟棄很多信息,諸如漸變之類的。

同時在轉化某些非path協議時,轉化效果也有點細節問題。比如轉化svg的ellipse時,它用了一系列的貝塞爾曲線Path來擬合橢圓,更簡化的方法應該是使用A命令來生成橢圓。所以這個工具也不是萬能的,大家不能全靠工具來生成xml。

還要注意,工具生成的xml內width/height屬性直接使用svg的畫布尺寸的,單位是dp,這樣的drawable可能會導致性能問題,所以要記得改成自己需要的寬高。

 

二、矢量圖形

 

2.1 XML定義

矢量圖形對應的XML文件定義在res/drawable下,在XML文件中的根標簽是

vector支持drawable相關的屬性,如width/height等(必須要設置,否則View是wrap_content時drawable沒寬高無法運行),還支持一些特定屬性,關鍵的有viewportWidth/viewportHeight,這兩個值代表虛擬畫布的寬高,後面的Path繪制裡的參數都是相對此畫布的寬高坐標系進行的。具體的屬性見下面2.2節。

 

vector標簽下支持0個或多個標簽,表示一組路徑的集合,在內定義一個或多個標簽,定義要被繪制的路徑,也可以不加,直接在下定義一個或多個標簽,這些path路徑標簽支持fillColor(填充顏色)/pathData(路徑)/strokeWidth/strokeColor等屬性。/標簽下還支持標簽。

 

如果要繪制的一塊區域,就使用填充顏色fillColor,則路徑起始點到路徑繪制的所有點的都有填充,如果要繪制的是路徑,則使用strokeWidth/strokeColor,不使用fillColor,來繪制路徑。

 

定義好一個XML後,就可以當正常的drawable資源使用了。下面是一個網上找到的心形路徑的XML定義:



    

pathData內的路徑命令列表代表的是一個心形圖案的展示。命令以M命令指定繪制點初始點開始,到z命令封閉路徑結束。pathData內支持上文提到的各種命令。將svg文件中path部分復制到此處,可以定義一個Android支持的矢量圖形。效果如下:

\

 

2.2 特性描述

 

2.1.1 概述

矢量圖形對應的Java類是VectorDrawable。VectorDrawable沒有提供setPathData之類的方法,所以我們只能在XML內定義矢量圖形。

為了優化重繪性能,每個VectorDrawable維護了一個Bitmap緩存。因此,使用同一個VectorDrawable的時候,引用的是同一個Bitmap緩存,如果兩個引用位置要求不同的圖像大小,每次大小發生變化的時候,bitmap都需要重新創建並重新繪制,這是一個非常大的開銷。所以,如果一個VectorDrawable在不同的時機需要不同的大小,更高效的方法是創建多個VectorDrawable,這樣每個Size都有一個VectorDrawable,從而減少bitmap操作導致的開銷。

 

2.1.2矢量圖形的xml標簽與屬性

矢量圖形的xml文件支持以下標簽:

根標簽,表示一個矢量動畫

支持的屬性:

1)android:name:定義矢量圖形的名稱

2)android:width:定義Drawable的寬度,支持所有dimension單位,一般使用dp。drawable的寬度不一定是最終繪制寬度,比如給ImageView設置backgroud則Drawable繪制寬度等於ImageView的寬度,給ImageView設置src則在ImageView大於Drawable寬度時,Drawable繪制寬度等於自己定義的寬度。

3)android:height:定義Drawable的寬度,支持所有dimension單位,一般是dp。其它同上。

4)android:viewportWidth:定義矢量圖形的視圖(viewport)空間的寬度,viewport是一個虛擬的canvas,後面所有的path都在該坐標系上繪制。坐標系左上方為(0,0),橫軸從左向右,縱軸從上到下。橫軸可視區域就是0~viewportWidth。

5)android:viewportHeight:定義矢量圖形的可視區域的高度。其它見上。[0,0]~[viewportWidth,viewportHeight]定義了虛擬canvas的可視區域。

6)android:tint:作為染色(tint)的色彩應用到drawable上。默認不應用tint。

7)android:tintMode:tint顏色的Porter-Duff混合模式,默認是src_in。

8)android:autoMirrored:如果drawable布局方向是RTL(right-to-left)時,drawable繪制是否需要鏡像化(鏡像化就是繞自身x軸中線旋轉180度)。

9)android:alpha:drawble的透明度,取值0~1

 

定義一組路徑和子group,另外還定義了轉換信息(transformation information)。轉換信息定義在vector指定的視圖區域內(與viewport坐標系相同)。定義的應用轉換的順序是縮放-->旋轉-->平移,所以同時定義的這些屬性最先應用scaleX/scaleY屬性,最後應用translateX/translateY屬性。

支持的屬性:

1)android:name:定義group的名稱

2)android:rotation:group對應矢量圖形的旋轉角度,取值是360度制。

3)android:pivotX:Group旋轉和縮放時的中心點的X軸坐標。取值基於viewport視圖的坐標系,不能使用百分比。

4)android:pivotY:Group旋轉和縮放時的中心點的Y軸坐標。取值基於viewport視圖的坐標系,不能使用百分比。

5)android:scaleX:Group在X軸上的縮放比例,最先應用到圖形上。

6)android:scaleY:Group在Y軸上的縮放比例,最先應用到圖形上。

7)android:translateX:Group在X軸的平移距離,取值基於viewport視圖的坐標系。最後應用到圖形上。

8)android:translateY:Group在Y軸的平移距離,取值基於viewport視圖的坐標系。最後應用到圖形上。

 

定義一個路徑,一個路徑即可以表示一塊填充區域也可以表示一根線條。

支持的屬性:

1)android:name:定義路徑的名稱

2)android:pathData:定義路徑的數據,路徑由多條命令組成,格式與SVG標准的path data的d屬性完全相同,路徑命令的參數定義在viewport視圖的坐標系。

3)android:fillColor:指定填充路徑的顏色,一般是一個顏色值,在SDK24及以上,可以指定一個顏色狀態列表或者一個漸變的顏色。如果在此屬性上做漸變動畫,新的屬性值會覆蓋此值。如果不指定,則path不被填充。

4)android:strokeColor:指定路徑線條的顏色,一般是一個顏色值,在SDK24及以上,可以指定一個顏色狀態列表或者一個漸變的顏色。如果在此屬性上做漸變動畫,新的屬性值會覆蓋此值。如果不指定,則path的線條不會繪制出來。

5)android:strokeWidth:指定路徑線條的寬度,基於viewport視圖的坐標系(不要dp/px之類的結尾)。

6)android:strokeAlpha:指定路徑線條的透明度。

7)android:fillAlpha:指定填充區域的透明度。

8)android:trimPathStart:取值從0到1,表示路徑從哪裡開始繪制。0~trimPathStart區間的路徑不會被繪制出來。

9)android:trimPathEnd:取值從0到1,表示路徑繪制到哪裡。trimPathEnd~1區間的路徑不會被繪制出來。

10)android:trimPathOffset:平移可繪制區域,取值從0到1,線條從(trimPathOffset+trimPathStart繪制到trimPathOffset+trimPathEnd),注意:trimPathOffset+trimPathEnd如果超過1,其實也是繪制的的,繪制的是0~trimPathOffset+trimPathEnd-1的位置。

11)android:strokeLineCap:設置線條首尾的外觀,三個值:butt(默認,向線條的每個末端添加平直的邊緣), round(向線條的每個末端添加圓形線帽), square(向線條的每個末端添加正方形線帽。)。

12)android:strokeLineJoin:設置當兩條線條交匯時,創建什麼樣的邊角(線段連接類型):三個值:miter(默認,創建尖角),round(創建圓角),bevel(創建斜角) 。

13)android:strokeMiterLimit:設置設置最大斜接長度,斜接長度指的是在兩條線交匯處內角和外角之間的距離。只有當 lineJoin 屬性為 "miter" 時,miterLimit 才有效。從asp" target="_blank">http://www.w3school.com.cn/tags/canvas_miterlimit.asp盜了個圖:

\

 

14)android:fillType:設置路徑的填充類型,與SVG格式的"fill-rule"屬性相同。見https://www.w3.org/TR/SVG/painting.html#FillRuleProperty。

 

定義當前裁切的路徑。裁切路徑只能用於當前group和其子元素,只有在裁切路徑內的元素才會被顯示出來。clip-path定義後才會影響後面path的繪制,如果一個group內有多個path,clip-path定義在第三位,則前面兩個path不受其影響,後面的path受其影響。如果希望clip-path對整個group都生效,應放在第一位。

支持的屬性:

1)android:name:定義裁切路徑的名稱

2)android:pathData:定義裁切路徑,取值與上面講的pathData相同。

 

2.3 一個簡單的笑臉(vector_drawable_smile_face.xml)



    

        

        

        

        

        

    

效果圖:

\

 

三、矢量動畫

 

首先要說明一點:矢量動畫其實是屬性動畫系統的一個應用。

矢量動畫可以有多種動畫效果:

group對應的旋轉/縮放/平移等效果是傳統的動畫效果。

path對應的屬性可以做出很多絢麗的效果。比如改變pathData屬性,可以做出形狀變化的動畫;改變trimPathStart/trimPathEnd可以做出繪制曲線路徑的效果;改變strokeColor可以做出線條顏色變化的效果。

clip-path的pathData變化可以做出各種形狀的揭開和遮擋的效果。

 

3.1 XML定義

XML定義一個矢量動畫需要完成三部曲:

1)在res/drawable內定義一個矢量圖形

2)在res/drawable內定義一個矢量動畫drawable

3)定義2中使用的屬性動畫

 

3.1.1 定義矢量圖形

在XML中定義一個矢量動畫,首先需要在res/drawablen內定義一個矢量圖形的XML。下面定義了一個三角形的XML(對應Java類VectorDrawable):


    
        
        
    

我們注意到,上面這個矢量圖內包含一個group標簽,和2個path標簽。group可以包含多個path標簽。這些標簽都做了命名,後面我們需要用標簽的名稱找到矢量圖形內的對象,並對其做動畫。

另外,看pathData部分,我們本來一個三角形的定義只需要M50,30 L 70,70 L 30,70 z即可,這裡多了一個無意義的L 50,30是干嘛的呢?這個我們後面再說。

 

3.1.2 定義矢量動畫

矢量圖形定義好了後,我們就需要指定矢量動畫了。矢量動畫在XML中對應的標簽是,其XML文件也定義在res/drawable內,所以本質上也是一個drawable資源,可以在布局中隨意使用。矢量動畫可以對上面的矢量圖形的整體或者一部分做動畫效果。也就是對元素做動畫。

對上圖的整體做效果,其實就是對rotateGroup做動畫,而對部分圖形做效果,我們選用第一個三角形triangle1,讓它過渡成一個矩形。下面是矢量動畫的定義(res/drawable/news_animator_drawable.xml):


    
    

可以看出,一個矢量動畫,包含了多個標簽,每個target標簽其實就是對上面定義的矢量圖形的整體或者局部指定動畫效果,如何確定對那塊圖形做動畫,就靠上面定義的矢量圖形塊中定義的名稱(android:name)字段了。對group和path的命名,幫助系統在動畫執行前從矢量圖形內找到它們。

 

3.1.3 定義屬性動畫

上面我們講到,矢量動畫是屬性動畫的一個應用。我們可以看到,每個target指定的動畫標簽都是一個屬性動畫。我們來看下這兩個矢量動畫的定義,rotate_animator動畫用於整體矢量圖形旋轉,path_change動畫用於將三角形轉化成四邊形:


上面一個屬性動畫我們很熟悉了,以前講的時候這種旋轉都是應用在View上,這次是應用在矢量圖形的group上,這說明矢量圖形的group標簽對應的java類有類似setRotation()之類的接口做圖形旋轉 。

 

下面這個屬性動畫我們比較陌生,不過其本質還是屬性動畫對類型為pathType的對象屬性值做插值。既然是插值,我們就需要兩者具有可比性,所以valueFrom和valueTo的值內的命令列表必須一一對應(每條命令的參數個數也必須相同),插值工作才能進行,這也就是上文中我們定義了一個無意義的L50,30命令的價值所在。

每次插值的結果,都會被設置到矢量圖形標簽的pathData屬性中,這樣界面刷新時,矢量圖形指定path繪制的圖案就不斷的刷新,從而產生動畫效果。

注意:再強調一遍,矢量動畫要求初始幀的路徑命令序列(valueFrom)與結束幀的路徑命令序列(valueTo)內的命令必須一一對應,只有參數值可以不同,這樣才能插值,從而矢量動畫才能執行。否則編譯後運行時就崩潰了。

 

3.1.4 集成運行動畫

這時候,矢量動畫已經定義好了,怎麼把它集成到View內執行動畫呢?

1)首先給一個ImageView定義src為剛剛定義的矢量動畫drawable:

 

2)在Java代碼內,通過取到AnimatedVectorDrawable,執行動畫:

AnimatedVectorDrawable animatedVectorDrawable =
        (AnimatedVectorDrawable) mImageView.getDrawable();
if(animatedVectorDrawable.isRunning()) {
    animatedVectorDrawable.stop();
} else {
    animatedVectorDrawable.start();
}

然後一個矢量動畫就運行起來喽!這段代碼是不是和幀動畫的啟動完全一致,對吧!因為它們都是Drawable的子對象,用法都差不多。

效果圖:

\

 

3.1.5 給笑臉做個動畫


    

    

    




效果:

\

 

3.2 路徑繪制過程動畫

矢量圖形的path標簽繪制時,存在兩個屬性trimPathStart、trimPathEnd,對這兩個屬性做屬性動畫可以得到路徑軌跡不斷繪制的效果,以第2個三角形triangle2為變化對象:

在矢量動畫定義的animated-vector中加入:

定義一個新的屬性動畫trimpathend_change.xml:


動畫執行後,path的trimPathEnd屬性從0變化到1的過程就是路徑不斷繪制出來的過程。

 

這裡要解釋下什麼是trimPathStart/trimPathEnd:

trimPathStart:開始路徑的百分比,取值在0~1,0表示從路徑開始位置繪制,整個路徑都可見,1表示路徑完全不繪制,整個路徑不可見;

trimPathEnd:結束路徑的百分比,取值在0~1,0表示繪制到路徑開始位置就不繪制,其實就是路徑不繪制,不可見,1表示繪制到路徑結束位置,所以整個路徑完全可見;

將路徑的長度歸一化,則一個Path繪制的可見區域應該是[trimPathStart,trimPathEnd]。

 

既然原理已經說清楚了,那麼我們來看個稍微復雜點的例子,大家肯定看到過一種系統自帶的轉圈動畫,箭頭轉圈的過程中,它後面已經繪制的圓弧不斷消失,最終一圈跑下來,又歸於原位。這種效果就可以用trimPathStart和trimPathEnd實現。trimPathStart是路徑開始繪制的位置,trimPathEnd是路徑結束繪制的位置。所以如果這兩個屬性都發生改變,但是trimPathStart抹去路徑繪制區域的速度慢於trimPathEnd的時候會怎麼樣呢?是不是就造成了這種轉圈效果呢?下面我就不繪制圓了,用上面的三角形triangle2做例子(res/animator/trimstartend_change.xml):


    

效果還可以,對吧!

\

 

四、兼容性問題

 

4.1 VectorDrawable的png生成策略

發布於Android 5.0的VectorDrawable,有一段時間官方是不支持低版本的。

Android build tools提供一種方案,如果編譯版本是5.0以下版本,則會把VectorDrawable生成對應的png圖片,這樣在5.0以下的版本則使用的是生成的png圖,而在5.0以上的版本中則使用VectorDrawable。

大家知道,Android有多個屏幕密度(ldpi/mdpi/hdpi/xhdpi/xxhdpi....),每個都生成一個一張png,那還不如一開始就切位圖呢!所以buid toos提供一個配置(build.gradle):

defaultConfig {
    applicationId "org.qcode.androidsvgdemo"
    minSdkVersion 9
    targetSdkVersion 23
    versionCode 1
    versionName "1.0"
    generatedDensities = [ 'hdpi', 'xhdpi' ]
}

minSdkVersion支持到9,此時generatedDensities生效(注意:如果minSdkVersion 21,則此屬性不生效,直接使用矢量圖xml)。generatedDensities = [ 'hdpi', 'xhdpi' ]表示只給hdpi和xhdpi生成png圖片。其他密度都不生成(此屬性不配置,就對所有屏幕密度都生成一份png):

\

這樣既能兼容老版本,又能在高版本上(drawable-anydpi-v21)上使用矢量圖形。

這裡還要注意另一個問題,正常情況下,我們可以通過@string/**來引用pathData,但如果生成png,則使用@string/**會報錯,此時pathData的內容只能寫在矢量圖形的xml文件內。

 

4.2 AnimatedVectorDrawable不兼容的解決

前面說了通過png生成來支持VectorDrawable在低版本的展示,但是AnimatedVectorDrawable沒辦法通過這種方式支持,所以在使用矢量動畫時需要注意:如果不考慮支持5.0之前的版本,則一切OK。否則應把矢量圖形資源放到 res/drawable目錄中,把矢量動畫放到 drawable-v21 目錄中,並在drawable 中提供一個和 AnimatedVectorDrawable同名字的資源來在 5.0之前的版本使用(這個資源可以考慮使用selector來做點效果)。

 

4.3 開發者社區的支持

https://github.com/trello/victor

https://github.com/telly/MrVector

https://github.com/wnafee/vector-compat

vector-compat相對比較好,不過後面google提供了官方支持,這些支持可以不用看了。

 

4.4 官方低版本支持

Android最終發布了官方Support包(support-vector-drawable)的VectorDrawableCompat做低版本兼容(最低支持到API 7)。所以如果我們使用VectorDrawableCompat加載矢量資源,就不需要再生成png了。

要在工程中支持低版本的矢量圖形和動畫,需要support0vector-drawable庫和23.2.0+的appcompat-v7庫(還要取消png生成,支持於android studio1.4) 。

compile 'com.android.support:appcompat-v7:23.2.0'編譯出support-vector-drawable-23.2.0和animated-vector-drawable-23.2.0這兩個庫。

工程配置方面,VectorDrawableCompat需要依賴aapt的一些功能,來保持最近矢量圖使用的添加的屬性ID,以便他們可以被v21之前的引用。想要的在build.gradle需要增加一些配置:

如果Gradle插件版本V2.0及以上,則需要加入:

android {
    defaultConfig {
       vectorDrawables.useSupportLibrary = true
    }
}

如果Gradle插件版本在V1.5及以下,則需要添加:

android {
     defaultConfig {
         //不生成png
         generatedDensities = []
     }

    aaptOptions {
         additionalParameters "--no-version-vectors"
    }
}

集成時需要注意:

1)使用android:src屬性的地方需要替換為app:srcCompat屬性。

2)在非src屬性的地方使用矢量圖時,需要將矢量圖用drawable容器(如StateListDrawable, InsetDrawable, LayerDrawable, LevelListDrawable, 和RotateDrawable)包裹起來使用。否則會在低版本的情況下報錯。

詳細的說明可以參考:http://www.tuicool.com/articles/3emUnmM

 

五、總結

 

本文總結了矢量圖形和矢量動畫相關的知識。下面再分析下Android5.0引入矢量圖形帶來的改變:

矢量圖形帶來的好處:

1)無限拉伸不失真,免去多個屏幕密度下集成多套切片的問題,減少安裝包體積

2)帶來了變形動畫的動畫方式(矢量變形動畫)

3)帶來了復雜路徑繪制的動畫方式(矢量路徑繪制動畫)

 

矢量圖形存在的缺陷:

1)兼容性問題:5.0以下版本的兼容性。

2)不完全支持SVG標准,SVG與VectorDrawable沒有可比性。我們不能直接在View上展示svg格式的圖片。VectorDrawable 支持SVG的一部分規則(主要是SVG中定義path部分的規則 ),我們基本上只能將svg中的Path定義的數據用在VectorDrawable的pathData中(其它標簽需要工具轉化成path)。

3)VectorDrawable內存有一個bitmap緩存,如果矢量圖可以確定要用於不同的圖像大小的場景,需要創建多個VectorDrawable,不能復用同一個VectorDrawable,否則會有性能問題。

 

問題雖然多多,但是矢量圖形和矢量動畫帶來的好處是不言而喻的,它們極大的豐富了屬性動畫的應用場景,Android5.0後系統的動畫越來越絢麗,很大程度上都與此相關。在Android應用爆炸發展的今天,精致的動畫效果已經成了應用拉用戶的一個很重要的方式,相信矢量動畫的應用場景會越來越豐富。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved