VectorDrawable怎么玩

摘要

從5.0(API等級21)開始絮重,android開始支持矢量圖了鼻吮。關(guān)于什么是矢量圖以及矢量圖有什么優(yōu)缺點(diǎn)不在本文的涉及范圍之內(nèi)剩燥,具體可以參考矢量圖百科澳骤。不過這里要提一下它的優(yōu)點(diǎn):

  • 保存最少的信息鼻种,文件大小比位圖要小反番,并且文件大小與物體的大小無關(guān)
  • 任意放大矢量圖形,不會丟失細(xì)節(jié)或影響清晰度叉钥,因?yàn)槭噶繄D形是與分辨率無關(guān)的罢缸。

從以上兩個(gè)優(yōu)點(diǎn)來看,在項(xiàng)目中使用矢量圖至少可以縮小我們apk包的尺寸投队,而且可以在屏幕適配時(shí)提供很大的方便枫疆,因?yàn)槭噶繄D是分辨率無關(guān)的。

前面也說了敷鸦,矢量圖從21才開始支持息楔。那么如果我想往下兼容改怎么辦呢?這個(gè)問題要放在以前的話扒披,我會說github下就有你要的答案值依。但現(xiàn)在我不會這么說,因?yàn)榍岸螘r(shí)間Google升級了support library碟案,官方向后兼容了矢量圖的使用愿险。要問兼容到哪個(gè)版本,我告訴你矢量圖兼容到API7价说,矢量圖動畫兼容到API11(是不是已經(jīng)滿足了你的使用)辆亏。

好了,下面我們就來說說怎么在項(xiàng)目中使用矢量圖熔任。

VectorDrawable的使用

按照官方的說法褒链,要在低版本上使用矢量圖唁情,需要在項(xiàng)目中引入新的兼容庫support-vector-drawable疑苔,并且appcompat-v7庫的版本要在23.2.0+(寫文章這會23.2.1已經(jīng)發(fā)布了)。而且你還要修改下gradle的相關(guān)配置甸鸟,不要讓gradle在構(gòu)建的時(shí)候?yàn)槟阍诘桶姹?API21以下)的情況下生成針對于不同密度的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自動生成不同屏幕分辨率的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中對應(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)包裹起來使用。否則會在低版本的情況下報(bào)錯(cuò)沪伙。

而在代碼中的使用和普通的png圖沒什么區(qū)別瓮顽,調(diào)用的是同樣的API。

這樣我們就把矢量圖引入到我們的項(xiàng)目中了围橡,下面我貼幾張圖來對比下矢量圖和png圖的不同暖混,以此來展示下矢量圖的優(yōu)點(diǎn)。

首先是png的原圖和放大圖


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


對比一目了然翁授。而且矢量圖的xml的大小只有655個(gè)字節(jié)拣播,而不同分辨率的png的大小加起來有好幾k。矢量圖只需要維護(hù)一個(gè)xml收擦,而png需要維護(hù)多個(gè)圖形資源贮配。

矢量圖xml文件支持的標(biāo)簽以及屬性可以參考這里,包括了常見的填充塞赂、描邊泪勒、著色等。

使用矢量圖制作動畫

23.2的支持庫同樣也放出了矢量圖動畫對應(yīng)的兼容版本AnimatedVectorDrawableCompat,對應(yīng)的兼容包是animated-vector-drawable圆存,xml標(biāo)簽則是animated-vector叼旋。AnimatedVectorDrawableCompat能夠以屬性動畫的形式來驅(qū)動VectorDrawable實(shí)現(xiàn)動畫,具體來說需要分三步走:

  • 定義一個(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)夫植、縮放、平移油讯。這些屬性值得變化會反應(yīng)在它內(nèi)部的path和subgroup元素上-->
    <group
        android:scaleX="5.0"
        android:scaleY="5.0">
        <!-- 這里group和path有一個(gè)name屬性详民,這個(gè)屬性用來在使用動畫時(shí)指定動畫要驅(qū)動的對象 -->
        <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ū)動的矢量圖對象阐斜。子標(biāo)簽target一方面用來指定要驅(qū)動的矢量圖內(nèi)的group和path的名稱(這里和VectorDrawableCompat的xml中的group和path名稱對應(yīng));另一方面指定要使用哪個(gè)屬性動畫來驅(qū)動group和path的屬性進(jìn)行變化來產(chǎn)生動畫效果诀紊。

  • 創(chuàng)建屬性動畫

驅(qū)動trimPathStart和strokeColor屬性的動畫

<?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)備工作就做好了。我們就可以使用矢量圖動畫了邻奠。把ImageView的src更改為矢量圖動畫

<ImageView
       android:id="@+id/image_view"
       android:layout_width="200dp"
       android:layout_height="200dp"
       app:srcCompat="@drawable/vector_drawable_anim" />

在Java代碼中啟動動畫

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)了矢量圖動畫笤喳,看看效果圖吧。

好了碌宴,關(guān)于矢量圖以及矢量圖動畫的使用就說這么多杀狡。具體的一些細(xì)節(jié)以及xml中的其他屬性啥的怎么使用可以參考官方文檔,自己親自試一試就會很明了了贰镣。源碼在這里呜象,歡迎star and fork。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末碑隆,一起剝皮案震驚了整個(gè)濱河市恭陡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌上煤,老刑警劉巖休玩,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異劫狠,居然都是意外死亡拴疤,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進(jìn)店門独泞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來呐矾,“玉大人,你說我怎么就攤上這事懦砂⊙逊福” “怎么了讲坎?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長愧薛。 經(jīng)常有香客問我,道長衫画,這世上最難降的妖魔是什么毫炉? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮削罩,結(jié)果婚禮上瞄勾,老公的妹妹穿的比我還像新娘。我一直安慰自己弥激,他們只是感情好进陡,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著微服,像睡著了一般趾疚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上以蕴,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天糙麦,我揣著相機(jī)與錄音,去河邊找鬼丛肮。 笑死赡磅,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的宝与。 我是一名探鬼主播焚廊,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼习劫!你這毒婦竟也來了咆瘟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤诽里,失蹤者是張志新(化名)和其女友劉穎搞疗,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體须肆,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡匿乃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了豌汇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片幢炸。...
    茶點(diǎn)故事閱讀 39,703評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖拒贱,靈堂內(nèi)的尸體忽然破棺而出宛徊,到底是詐尸還是另有隱情佛嬉,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布闸天,位于F島的核電站暖呕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏苞氮。R本人自食惡果不足惜湾揽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望笼吟。 院中可真熱鬧库物,春花似錦、人聲如沸贷帮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽撵枢。三九已至民晒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間锄禽,已是汗流浹背镀虐。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留沟绪,地道東北人刮便。 一個(gè)月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像绽慈,于是被迫代替她去往敵國和親恨旱。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內(nèi)容