如何玩轉(zhuǎn)Android矢量圖VectorDrawable
從5.0(API等級(jí)21)開始,android開始支持矢量圖了。關(guān)于什么是矢量圖以及矢量圖有什么優(yōu)缺點(diǎn)不在本文的涉及范圍之內(nèi),具體可以參考矢量圖百科。不過這里要提一下它的優(yōu)點(diǎn):
保存最少的信息,文件大小比位圖要小,并且文件大小與物體的大小無關(guān)
任意放大矢量圖形,不會(huì)丟失細(xì)節(jié)或影響清晰度,因?yàn)槭噶繄D形是與分辨率無關(guān)的。
從以上兩個(gè)優(yōu)點(diǎn)來看,在項(xiàng)目中使用矢量圖至少可以縮小我們apk包的尺寸,而且可以在屏幕適配時(shí)提供很大的方便,因?yàn)槭噶繄D是分辨率無關(guān)的。
前面也說了,矢量圖從21才開始支持。那么如果我想往下兼容改怎么辦呢?這個(gè)問題要放在以前的話,我會(huì)說github下就有你要的答案。但現(xiàn)在我不會(huì)這么說,因?yàn)榍岸螘r(shí)間Google升級(jí)了support library,官方向后兼容了矢量圖的使用。要問兼容到哪個(gè)版本,我告訴你矢量圖兼容到API7,矢量圖動(dòng)畫兼容到API11(是不是已經(jīng)滿足了你的使用)。
好了,下面我們就來說說怎么在項(xiàng)目中使用矢量圖。
一、VectorDrawable的使用
按照官方的說法,要在低版本上使用矢量圖,需要在項(xiàng)目中引入新的兼容庫support-vector-drawable,并且appcompat-v7庫的版本要在23.2.0+(寫文章這會(huì)23.2.1已經(jīng)發(fā)布了)。而且你還要修改下gradle的相關(guān)配置,不要讓gradle在構(gòu)建的時(shí)候?yàn)槟阍诘桶姹?API21以下)的情況下生成針對(duì)于不同密度的png文件,因?yàn)閍ndroid studio1.4的時(shí)候支持了矢量圖。
修改appcompat-v7的版本
compile 'com.android.support:appcompat-v7:23.2.0'
NOTE: 這里我只引入了23.2.0版本的appcompat-v7庫,同步gradle后就編譯出了support-vector-drawable-23.2.0和animated-vector-drawable-23.2.0這兩個(gè)庫。
修改gradle配置文件
如果你的gradle插件的版本為2.0以下,你應(yīng)該這么修改
android { defaultConfig { // 不讓gradle自動(dòng)生成不同屏幕分辨率的png圖 generatedDensities = [] } aaptOptions { additionalParameters "--no-version-vectors" } }
如果你的gradle插件版本是2.0+,你 應(yīng)該這么修改
android { defaultConfig { vectorDrawables.useSupportLibrary = true } }
經(jīng)過上面這幾步的修改,你就可以在項(xiàng)目中使用矢量圖了。那么,下面我們就正式來說說怎么使用。
android studio為我們提供了一個(gè)Vector Asset Studio的工具,讓我么可以從material icon和svg文件生成矢量圖。具體用法可以參考官方的說明文檔,這里就不多說了。
Android中矢量圖是以xml文檔的形式存在的,像下面這樣就定義了一個(gè)矢量圖,里面包含了關(guān)于該矢量圖的數(shù)據(jù)信息。
<!-- res/drawable/heart.xml --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportHeight="24.0" android:viewportWidth="24.0"> <path android:fillColor="#FF000000" android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8zM15.5,11c0.83,0 1.5,-0.67 1.5,-1.5S16.33,8 15.5,8 14,8.67 14,9.5s0.67,1.5 1.5,1.5zM8.5,11c0.83,0 1.5,-0.67 1.5,-1.5S9.33,8 8.5,8 7,8.67 7,9.5 7.67,11 8.5,11zM12,17.5c2.33,0 4.31,-1.46 5.11,-3.5L6.89,14c0.8,2.04 2.78,3.5 5.11,3.5z" /> </vector>
這是我通過material icon生成的,它在android中對(duì)應(yīng)著VectorDrawable這個(gè)類,也就是兼容包中的VectorDrawableCompat這個(gè)類。
定義好矢量圖形后,我們就可以向普通的圖形那樣來使用它了。不過有幾點(diǎn)需要注意:
*使用android:src屬性的地方需要替換為app:srcCompat屬性
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.damon.vectordrawabledemo.MainActivity"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" app:srcCompat="@drawable/ic_mood_black_24dp" /> </RelativeLayout>
*在非src屬性的地方使用矢量圖時(shí),需要將矢量圖用drawable容器(如StateListDrawable, InsetDrawable, LayerDrawable, LevelListDrawable, 和RotateDrawable)包裹起來使用。否則會(huì)在低版本的情況下報(bào)錯(cuò)。
而在代碼中的使用和普通的png圖沒什么區(qū)別,調(diào)用的是同樣的API。
這樣我們就把矢量圖引入到我們的項(xiàng)目中了,下面我貼幾張圖來對(duì)比下矢量圖和png圖的不同,以此來展示下矢量圖的優(yōu)點(diǎn)。
首先是png的原圖和放大圖
其次是矢量圖的原圖和放大圖
對(duì)比一目了然。而且矢量圖的xml的大小只有655個(gè)字節(jié),而不同分辨率的png的大小加起來有好幾k。矢量圖只需要維護(hù)一個(gè)xml,而png需要維護(hù)多個(gè)圖形資源。
矢量圖xml文件支持的標(biāo)簽以及屬性可以參考這里,包括了常見的填充、描邊、著色等。
二、使用矢量圖制作動(dòng)畫
23.2的支持庫同樣也放出了矢量圖動(dòng)畫對(duì)應(yīng)的兼容版本AnimatedVectorDrawableCompat,對(duì)應(yīng)的兼容包是animated-vector-drawable,xml標(biāo)簽則是animated-vector。AnimatedVectorDrawableCompat能夠以屬性動(dòng)畫的形式來驅(qū)動(dòng)VectorDrawable實(shí)現(xiàn)動(dòng)畫,具體來說需要分三步走:
*定義一個(gè)VectorDrawableCompat的xml
<vector xmlns:android="http://schemas.android.com/apk/res/android" <!-- 圖片本身的大小 --> android:width="500px" android:height="500px" <!-- 畫布的大小 --> android:viewportHeight="500" android:viewportWidth="500"> <!-- 用來把多個(gè)path或者subgroup組合起來,group提供了一些屬性比如旋轉(zhuǎn)、縮放、平移。這些屬性值得變化會(huì)反應(yīng)在它內(nèi)部的path和subgroup元素上--> <group android:scaleX="5.0" android:scaleY="5.0"> <!-- 這里group和path有一個(gè)name屬性,這個(gè)屬性用來在使用動(dòng)畫時(shí)指定動(dòng)畫要驅(qū)動(dòng)的對(duì)象 --> <path android:name="star" android:pathData="M 50.0,90.0 L 82.9193546357,27.2774101308 L 12.5993502926,35.8158045183 L 59.5726265715,88.837672697 L 76.5249063296,20.0595700732 L 10.2916450361,45.1785327898 L 68.5889268818,85.4182410261 L 68.5889268818,14.5817589739 L 10.2916450361,54.8214672102 L 76.5249063296,79.9404299268 L 59.5726265715,11.162327303 L 12.5993502926,64.1841954817 L 82.9193546357,72.7225898692 L 50.0,10.0 L 17.0806453643,72.7225898692 L 87.4006497074,64.1841954817 L 40.4273734285,11.162327303 L 23.4750936704,79.9404299268 L 89.7083549639,54.8214672102 L 31.4110731182,14.5817589739 L 31.4110731182,85.4182410261 L 89.7083549639,45.1785327898 L 23.4750936704,20.0595700732 L 40.4273734285,88.837672697 L 87.4006497074,35.8158045183 L 17.0806453643,27.2774101308 L 50.0,90.0Z" android:strokeColor="@color/colorAccent" android:strokeWidth="2" /> </group> </vector>
*定義AnimatedVectorDrawableCompat的xml
<?xml version="1.0" encoding="utf-8"?> <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/vector_drawable"> <target android:name="star" android:animation="@animator/star_anim" /> </animated-vector>
可以看到,根元素是animated-vector,并且有一個(gè)必須的屬性android:drawable用來指定要驅(qū)動(dòng)的矢量圖對(duì)象。子標(biāo)簽target一方面用來指定要驅(qū)動(dòng)的矢量圖內(nèi)的group和path的名稱(這里和VectorDrawableCompat的xml中的group和path名稱對(duì)應(yīng));另一方面指定要使用哪個(gè)屬性動(dòng)畫來驅(qū)動(dòng)group和path的屬性進(jìn)行變化來產(chǎn)生動(dòng)畫效果。
*創(chuàng)建屬性動(dòng)畫
驅(qū)動(dòng)trimPathStart和strokeColor屬性的動(dòng)畫
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <objectAnimator android:duration="5000" android:propertyName="trimPathStart" android:repeatCount="infinite" android:repeatMode="restart" android:valueFrom="1" android:valueTo="0" /> <objectAnimator android:duration="5000" android:propertyName="strokeColor" android:repeatCount="infinite" android:repeatMode="restart" android:valueFrom="@color/colorAccent" android:valueTo="@color/colorPrimaryDark" /> </set>
這樣,準(zhǔn)備工作就做好了。我們就可以使用矢量圖動(dòng)畫了。把ImageView的src更改為矢量圖動(dòng)畫
<ImageView android:id="@+id/image_view" android:layout_width="200dp" android:layout_height="200dp" app:srcCompat="@drawable/vector_drawable_anim" />
在Java代碼中啟動(dòng)動(dòng)畫
ImageView imageView = (ImageView) findViewById(R.id.image_view); Drawable drawable = imageView.getDrawable(); //AnimatedVectorDrawableCompat實(shí)現(xiàn)了Animatable接口 if (drawable instanceof Animatable){ ((Animatable) drawable).start(); }
這樣就實(shí)現(xiàn)了矢量圖動(dòng)畫,看看效果圖吧。
好了,關(guān)于矢量圖以及矢量圖動(dòng)畫的使用就說這么多。具體的一些細(xì)節(jié)以及xml中的其他屬性啥的怎么使用可以參考官方文檔,自己親自試一試就會(huì)很明了了。
文/DamonZh(簡(jiǎn)書作者)
原文鏈接:http://www.jianshu.com/p/456df1434739
相關(guān)文章
Android中自定義加載樣式圖片的具體實(shí)現(xiàn)
想實(shí)現(xiàn)下面這張圖中的自定義加載樣式,其實(shí)很簡(jiǎn)單,首先我們需要的布局組件有ProcessBar和TextView,下面是布局文件的代碼2014-04-04Android Path繪制貝塞爾曲線實(shí)現(xiàn)QQ拖拽泡泡
本文主要介紹Android Path繪制貝塞爾曲線,這里整理相關(guān)資料并運(yùn)用貝塞爾曲線實(shí)現(xiàn)QQ拖拽泡泡的示例,有興趣的小伙伴可以參考下2016-09-09Android編程實(shí)現(xiàn)GPS位置獲取的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)GPS位置獲取的方法,結(jié)合具體實(shí)例形式分析了Android針對(duì)GPS定位的常見操作技巧,需要的朋友可以參考下2017-07-07Android 網(wǎng)絡(luò)html源碼查看器詳解及實(shí)例
這篇文章主要介紹了Android 網(wǎng)絡(luò)html源碼查看器詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-03-03Android Moveview滑屏移動(dòng)視圖類完整實(shí)例
這篇文章主要介紹了Android Moveview滑屏移動(dòng)視圖類,很有實(shí)用價(jià)值,需要的朋友可以參考下2014-07-07Android viewpager中動(dòng)態(tài)添加view并實(shí)現(xiàn)偽無限循環(huán)的方法
這篇文章主要介紹了Android viewpager中動(dòng)態(tài)添加view并實(shí)現(xiàn)偽無限循環(huán)的方法,涉及Android使用viewpager動(dòng)態(tài)加載view及view無限循環(huán)顯示的相關(guān)技巧,需要的朋友可以參考下2016-01-01