如何玩轉(zhuǎn)Android矢量圖VectorDrawable
從5.0(API等級(jí)21)開(kāi)始,android開(kāi)始支持矢量圖了。關(guān)于什么是矢量圖以及矢量圖有什么優(yōu)缺點(diǎn)不在本文的涉及范圍之內(nèi),具體可以參考矢量圖百科。不過(guò)這里要提一下它的優(yōu)點(diǎn):
保存最少的信息,文件大小比位圖要小,并且文件大小與物體的大小無(wú)關(guān)
任意放大矢量圖形,不會(huì)丟失細(xì)節(jié)或影響清晰度,因?yàn)槭噶繄D形是與分辨率無(wú)關(guān)的。
從以上兩個(gè)優(yōu)點(diǎn)來(lái)看,在項(xiàng)目中使用矢量圖至少可以縮小我們apk包的尺寸,而且可以在屏幕適配時(shí)提供很大的方便,因?yàn)槭噶繄D是分辨率無(wú)關(guān)的。
前面也說(shuō)了,矢量圖從21才開(kāi)始支持。那么如果我想往下兼容改怎么辦呢?這個(gè)問(wèn)題要放在以前的話(huà),我會(huì)說(shuō)github下就有你要的答案。但現(xiàn)在我不會(huì)這么說(shuō),因?yàn)榍岸螘r(shí)間Google升級(jí)了support library,官方向后兼容了矢量圖的使用。要問(wèn)兼容到哪個(gè)版本,我告訴你矢量圖兼容到API7,矢量圖動(dòng)畫(huà)兼容到API11(是不是已經(jīng)滿(mǎn)足了你的使用)。
好了,下面我們就來(lái)說(shuō)說(shuō)怎么在項(xiàng)目中使用矢量圖。
一、VectorDrawable的使用
按照官方的說(shuō)法,要在低版本上使用矢量圖,需要在項(xiàng)目中引入新的兼容庫(kù)support-vector-drawable,并且appcompat-v7庫(kù)的版本要在23.2.0+(寫(xiě)文章這會(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庫(kù),同步gradle后就編譯出了support-vector-drawable-23.2.0和animated-vector-drawable-23.2.0這兩個(gè)庫(kù)。
修改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)過(guò)上面這幾步的修改,你就可以在項(xiàng)目中使用矢量圖了。那么,下面我們就正式來(lái)說(shuō)說(shuō)怎么使用。
android studio為我們提供了一個(gè)Vector Asset Studio的工具,讓我么可以從material icon和svg文件生成矢量圖。具體用法可以參考官方的說(shuō)明文檔,這里就不多說(shuō)了。
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>
這是我通過(guò)material icon生成的,它在android中對(duì)應(yīng)著VectorDrawable這個(gè)類(lèi),也就是兼容包中的VectorDrawableCompat這個(gè)類(lèi)。
定義好矢量圖形后,我們就可以向普通的圖形那樣來(lái)使用它了。不過(guò)有幾點(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)包裹起來(lái)使用。否則會(huì)在低版本的情況下報(bào)錯(cuò)。
而在代碼中的使用和普通的png圖沒(méi)什么區(qū)別,調(diào)用的是同樣的API。
這樣我們就把矢量圖引入到我們的項(xiàng)目中了,下面我貼幾張圖來(lái)對(duì)比下矢量圖和png圖的不同,以此來(lái)展示下矢量圖的優(yōu)點(diǎn)。
首先是png的原圖和放大圖


其次是矢量圖的原圖和放大圖


對(duì)比一目了然。而且矢量圖的xml的大小只有655個(gè)字節(jié),而不同分辨率的png的大小加起來(lái)有好幾k。矢量圖只需要維護(hù)一個(gè)xml,而png需要維護(hù)多個(gè)圖形資源。
矢量圖xml文件支持的標(biāo)簽以及屬性可以參考這里,包括了常見(jiàn)的填充、描邊、著色等。
二、使用矢量圖制作動(dòng)畫(huà)
23.2的支持庫(kù)同樣也放出了矢量圖動(dòng)畫(huà)對(duì)應(yīng)的兼容版本AnimatedVectorDrawableCompat,對(duì)應(yīng)的兼容包是animated-vector-drawable,xml標(biāo)簽則是animated-vector。AnimatedVectorDrawableCompat能夠以屬性動(dòng)畫(huà)的形式來(lái)驅(qū)動(dòng)VectorDrawable實(shí)現(xiàn)動(dòng)畫(huà),具體來(lái)說(shuō)需要分三步走:
*定義一個(gè)VectorDrawableCompat的xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
<!-- 圖片本身的大小 -->
android:width="500px"
android:height="500px"
<!-- 畫(huà)布的大小 -->
android:viewportHeight="500"
android:viewportWidth="500">
<!-- 用來(lái)把多個(gè)path或者subgroup組合起來(lái),group提供了一些屬性比如旋轉(zhuǎn)、縮放、平移。這些屬性值得變化會(huì)反應(yīng)在它內(nèi)部的path和subgroup元素上-->
<group
android:scaleX="5.0"
android:scaleY="5.0">
<!-- 這里group和path有一個(gè)name屬性,這個(gè)屬性用來(lái)在使用動(dòng)畫(huà)時(shí)指定動(dòng)畫(huà)要驅(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用來(lái)指定要驅(qū)動(dòng)的矢量圖對(duì)象。子標(biāo)簽target一方面用來(lái)指定要驅(qū)動(dòng)的矢量圖內(nèi)的group和path的名稱(chēng)(這里和VectorDrawableCompat的xml中的group和path名稱(chēng)對(duì)應(yīng));另一方面指定要使用哪個(gè)屬性動(dòng)畫(huà)來(lái)驅(qū)動(dòng)group和path的屬性進(jìn)行變化來(lái)產(chǎn)生動(dòng)畫(huà)效果。
*創(chuàng)建屬性動(dòng)畫(huà)
驅(qū)動(dòng)trimPathStart和strokeColor屬性的動(dòng)畫(huà)
<?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)畫(huà)了。把ImageView的src更改為矢量圖動(dòng)畫(huà)
<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)畫(huà)
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)畫(huà),看看效果圖吧。

好了,關(guān)于矢量圖以及矢量圖動(dòng)畫(huà)的使用就說(shuō)這么多。具體的一些細(xì)節(jié)以及xml中的其他屬性啥的怎么使用可以參考官方文檔,自己親自試一試就會(huì)很明了了。
文/DamonZh(簡(jiǎn)書(shū)作者)
原文鏈接:http://www.jianshu.com/p/456df1434739
相關(guān)文章
Android基于開(kāi)源項(xiàng)目xutils3實(shí)現(xiàn)下載
這篇文章主要介紹了Android基于開(kāi)源項(xiàng)目xutils3實(shí)現(xiàn)下載,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11
Android中RecyclerView實(shí)現(xiàn)多級(jí)折疊列表效果(二)
這篇文章主要給大家介紹了Android中RecyclerView實(shí)現(xiàn)多級(jí)折疊列表的相關(guān)資料,文中介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-05-05
Android studio導(dǎo)出APP測(cè)試包和構(gòu)建正式簽名包
大家好,本篇文章主要講的是Android studio導(dǎo)出APP測(cè)試包和構(gòu)建正式簽名包,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話(huà)記得收藏一下2021-12-12
Android實(shí)現(xiàn)登錄注冊(cè)功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)登錄注冊(cè)功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04
Android ProgressDialog的實(shí)例詳解
這篇文章主要介紹了Android ProgressDialog的實(shí)例詳解的相關(guān)資料,Android 開(kāi)發(fā)項(xiàng)目的時(shí)候經(jīng)常會(huì)遇到耗時(shí)的操作,這里就講下Android ProgressDialog的應(yīng)用,需要的朋友可以參考下2017-07-07
Android利用Intent啟動(dòng)和關(guān)閉Activity
這篇文章主要為大家詳細(xì)介紹了Android利用Intent啟動(dòng)和關(guān)閉Activity的相關(guān)操作,感興趣的小伙伴們可以參考一下2016-06-06
Android實(shí)現(xiàn)左滑關(guān)閉窗口
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)左滑關(guān)閉窗口,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04
Android移動(dòng)開(kāi)發(fā)recycleView的頁(yè)面點(diǎn)擊跳轉(zhuǎn)設(shè)計(jì)實(shí)現(xiàn)
這篇文章主要介紹了Android移動(dòng)開(kāi)發(fā)recycleView的頁(yè)面點(diǎn)擊跳轉(zhuǎn)設(shè)計(jì)實(shí)現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
Android水波紋載入控件CircleWaterWaveView使用詳解
這篇文章主要為大家詳細(xì)介紹了Android水波紋載入控件CircleWaterWaveView使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01

