編輯:關於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個或多個
如果要繪制的一塊區域,就使用填充顏色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
支持的屬性:
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。
支持的屬性:
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):
可以看出,一個矢量動畫,包含了多個
3.1.3 定義屬性動畫
上面我們講到,矢量動畫是屬性動畫的一個應用。我們可以看到,每個target指定的動畫標簽都是一個屬性動畫。我們來看下這兩個矢量動畫的定義,rotate_animator動畫用於整體矢量圖形旋轉,path_change動畫用於將三角形轉化成四邊形:
上面一個屬性動畫我們很熟悉了,以前講的時候這種旋轉都是應用在View上,這次是應用在矢量圖形的group上,這說明矢量圖形的group標簽對應的java類有類似setRotation()之類的接口做圖形旋轉 。
下面這個屬性動畫我們比較陌生,不過其本質還是屬性動畫對類型為pathType的對象屬性值做插值。既然是插值,我們就需要兩者具有可比性,所以valueFrom和valueTo的值內的命令列表必須一一對應(每條命令的參數個數也必須相同),插值工作才能進行,這也就是上文中我們定義了一個無意義的L50,30命令的價值所在。
每次插值的結果,都會被設置到矢量圖形
注意:再強調一遍,矢量動畫要求初始幀的路徑命令序列(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應用爆炸發展的今天,精致的動畫效果已經成了應用拉用戶的一個很重要的方式,相信矢量動畫的應用場景會越來越豐富。
上幾篇講contact的時候,取得的頭像都是存在數據庫中,通過: cursor = context.getContentResolver().query(
1、產生背景: 為了調試方便,常常希望通過知道apk的路徑,直接去啟動它,所以就寫了這個命令 2、使用方法: adb push launch /data/ adb pus
TextView是Android裡面用的最多的UI組件,一般使用在需要顯示一些信息的時候,其不能輸入,只能初始設定或者在程序中修改。 實例:TextViewDemo
本文實例講述了Android編程實現隱藏狀態欄及測試Activity是否活動的方法。分享給大家供大家參考,具體如下:一、 隱藏狀態欄方法如下:在程序中加入//remove