SVG在Android中的使用

SVG是什么沐兵,使用它的優(yōu)勢(shì)

SVG是指可伸縮矢量圖形 (Scalable Vector Graphics)遭居,它不同于傳統(tǒng)的位圖,不是通過(guò)存儲(chǔ)圖像中每一點(diǎn)的像素值來(lái)保存與使用圖形烂瘫,而是通過(guò) XML 文件來(lái)定義一個(gè)圖形黔夭。SVG 的方式是事先定義好怎么去畫(huà)這個(gè)圖胳施,然后等要用的時(shí)候再把它去畫(huà)出來(lái)溯祸。
SVG的優(yōu)劣如下:

  • SVG 是在要用圖的時(shí)候再把圖畫(huà)出來(lái),所以理所當(dāng)然的在圖片顯示的時(shí)候會(huì)花費(fèi)更多的時(shí)間消耗更多的資源。
  • 同樣由于上一個(gè)原因焦辅, SVG 并不太適合層次過(guò)于復(fù)雜細(xì)節(jié)過(guò)于繁多的圖片博杖。
  • 位圖是事先已經(jīng)畫(huà)好的圖片,所以適應(yīng)性必然沒(méi)有 SVG 好筷登,同一張圖片在不同分辨率下顯示會(huì)有差異剃根。
  • SVG 的文件里存儲(chǔ)了繪制圖片的相關(guān)信息,所以我們能夠?qū)D片的線條有一個(gè)非常清晰的感知前方,這在做動(dòng)畫(huà)的時(shí)候特別有用狈醉。
  • SVG 沒(méi)有存儲(chǔ)任何圖像的像素信息,所以 SVG 的文件體積遠(yuǎn)小于傳統(tǒng)的位圖文件惠险。
  • SVG 的文件畫(huà)出來(lái)的圖像是矢量圖苗傅,所以不會(huì)存在失真的問(wèn)題,理論上支持任何級(jí)別的縮放莺匠。

但是金吗,要注意Android對(duì)于 SVG 的支持是從 Android L 開(kāi)始的十兢,它的 SDK 里面加入了 VectorDrawable , AnimatedVectorDrawable 等類幫助我們構(gòu)建 SVG 圖形以及動(dòng)畫(huà)趣竣,并且你可以在 xml 文件里面直接使用 <vector/> 標(biāo)簽繪制 SVG 圖像以及 <animated-vector/> 標(biāo)簽為 SVG 圖像分配動(dòng)畫(huà)。

SVG的配置

android{
  ...
  defaultConfig {
    ...
    vectorDrawables.useSupportLibrary = true
   }
  ...
}
dependencies {
  ...
  compile "com.android.support:appcompat-v7:21+" // 至少Api21
  ...
}

項(xiàng)目的Activity中都包含(通用做法是在BaseActivity中加)

static {
  AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
AppCompatImageView
<android.support.v7.widget.AppCompatImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@drawable/svg_ic_arrow_right"/>
SVG參數(shù)相關(guān)

先看一個(gè)簡(jiǎn)單的SVG代碼

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="132dp"
        android:height="132dp"
        android:viewportHeight="132.0"
        android:viewportWidth="132.0">
    <path
        android:pathData="M50,2 L80.813,2 L80.813,130 L50,130 L50,2 Z"
        android:strokeColor="#e33e2b"
        android:strokeWidth="8" />
</vector>

效果如下:

vector屬性介紹
屬性 描述
android:name 定義VectorDrawable的名字
android:width/android:height 定義圖片的寬旱物、高遥缕,支持所有尺寸單位,通常用dp指定
android:viewportWidth/android:viewportHeight 定義圖片被劃分的比例大小宵呛,例如上面的600.0单匣,即把64dp平均分成500份,后面Path標(biāo)簽中的坐標(biāo)宝穗,就全部使用的是這里劃分后的坐標(biāo)系統(tǒng),width和height這兩個(gè)值必須一樣,否則圖片會(huì)出現(xiàn)變形诱担。
android:tint 定義圖片的顏色定血,默認(rèn)不設(shè)置顏色,該值會(huì)覆蓋path標(biāo)簽中的android:fillColor值
android:tintMode 定義圖片顏色為Porter-Duff blending 模式须鼎,默認(rèn)值為 src_in
android:autoMirrored 當(dāng)布局方向從右到左時(shí)鲸伴,該圖片是否自動(dòng)被鏡像
android:alpha 圖片的透明度,取值范圍(0-255)晋控,255表示全透明
group屬性介紹

包含一組path或子group汞窗,通過(guò)group可以把多個(gè)path組合到一塊形成一個(gè)圖片

屬性 描述
android:name 定義group的名字
android:rotation 定義group順時(shí)針旋轉(zhuǎn)的角度
android:pivotX、android:pivotY (pivotX赡译,pivotY)定義了group縮放仲吏、旋轉(zhuǎn)時(shí)的中心點(diǎn)
android:scaleX、android:scaleY X軸、Y軸的縮放倍數(shù)
android:translateX蜘矢、android:translateY X軸狂男、Y軸的平移倍數(shù)
path屬性介紹

定義被繪制的路徑

屬性 描述
android:name 定義路徑名字
android:pathData 定義矢量圖的路徑信息
android:fillColor 定義填充路徑的顏色,沒(méi)有定義不填充
android:strokeColor 定義路徑邊框的顏色
android:strokeWidth 定義路徑邊框的寬度
android:strokeAlpha 定義路徑邊框顏色的透明度
android:fillAlpha 定義填充路徑顏色的透明度
android:trimPathStart品腹、android:trimPathEnd 取值范圍都是(0,1)岖食,意思是截取從起始部分到結(jié)束部分的部分path
android:trimPathOffset 設(shè)置路徑截取區(qū)域,取值范圍(0,1)
android:strokeLineCap 設(shè)置路徑線帽的形狀舞吭,取值為 butt, round, square
android:strokeLineJoin 設(shè)置路徑交界處的連接方式泡垃,取值為 miter,round,bevel
android:strokeMiterLimit 設(shè)置斜角的上限
clip-path屬性介紹

定義當(dāng)前繪制的剪切路徑。注意羡鸥,clip-path 只對(duì)當(dāng)前的 group 和子 group 有效

屬性 描述
android:name 定義clip-path名字
android:pathData 類似于path中的pathdata,定義路徑信息
pathData里面繪制圖形的一些基本語(yǔ)法:
  • M = moveto(M X,Y):將畫(huà)筆移動(dòng)到指定的坐標(biāo)位置蔑穴,但未發(fā)生繪制
  • L = lineto(L X,Y):畫(huà)直線到指定的坐標(biāo)位置
  • H = horizontal lineto(H X):畫(huà)水平線到指定的X軸坐標(biāo)
  • V = vertical lineto(V Y):畫(huà)垂直線到指定的Y軸坐標(biāo)
  • C = curveto(C X1,Y1,X2,Y2,ENDX,ENDY):三次貝塞曲線
  • S = smooth curveto(S X2,Y2,ENDX,ENDY):三次貝塞曲線
  • Q = quadratic Belzier curveto(Q X,Y,ENDX,ENDY):二次貝塞曲線
  • T = smooth quadratic Belzier curveto(T ENDX,ENDY):映射前面路徑后的終點(diǎn)
  • A = elliptical Arc(A RX,RY,XROTATION,FLAG1,FLAG2,X,Y):弧線
  • Z = closepath():關(guān)閉路徑

注意:上述所有指令大小寫(xiě)均可。大寫(xiě)表示絕對(duì)定位惧浴,參照全局坐標(biāo)系存和;小寫(xiě)表示相對(duì)定位,參照父容器坐標(biāo)系衷旅。指令和數(shù)據(jù)間的空格可以省略捐腿。同一指令出現(xiàn)多次可以只用一個(gè)。

所以剛剛的簡(jiǎn)單代碼的意思是

M50,2 L80.813,2 L80.813,130 L50,130 L50,2 Z
//移動(dòng)到M(50,2)的位置柿顶,并且畫(huà)了封閉的四根線L(X,Y)... 最后Z:結(jié)束繪圖
SVG完整例子

icon_vector.xml : 繪圖xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="200dp"
    android:height="200dp"
    android:tint="@color/colorAccent"
    android:viewportHeight="24.0"
    android:viewportWidth="24.0">
    <path
        android:name="icon_path"
        android:fillColor="#FF000000"
        android:pathData="M6,18c0,0.55 0.45,1 1,1h1v3.5c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5L11,19h2v3.5c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5L16,19h1c0.55,0 1,-0.45 1,-1L18,8L6,8v10zM3.5,8C2.67,8 2,8.67 2,9.5v7c0,0.83 0.67,1.5 1.5,1.5S5,17.33 5,16.5v-7C5,8.67 4.33,8 3.5,8zM20.5,8c-0.83,0 -1.5,0.67 -1.5,1.5v7c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5v-7c0,-0.83 -0.67,-1.5 -1.5,-1.5zM15.53,2.16l1.3,-1.3c0.2,-0.2 0.2,-0.51 0,-0.71 -0.2,-0.2 -0.51,-0.2 -0.71,0l-1.48,1.48C13.85,1.23 12.95,1 12,1c-0.96,0 -1.86,0.23 -2.66,0.63L7.85,0.15c-0.2,-0.2 -0.51,-0.2 -0.71,0 -0.2,0.2 -0.2,0.51 0,0.71l1.31,1.31C6.97,3.26 6,5.01 6,7h12c0,-1.99 -0.97,-3.75 -2.47,-4.84zM10,5L9,5L9,4h1v1zM15,5h-1L14,4h1v1z"
        android:trimPathEnd="1.0"
        android:trimPathStart="0.0" />
</vector>

anim_icon.xml : 定義動(dòng)畫(huà)的XML

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="sequentially">
    <objectAnimator
        android:duration="2000"
        android:propertyName="trimPathStart"
        android:valueFrom="0.0"
        android:valueTo="1.0" />
    <objectAnimator
        android:duration="2000"
        android:propertyName="trimPathStart"
        android:valueFrom="1.0"
        android:valueTo="0.0" />
</set>

icon_vector_anim.xml : AnimatedVectorDrawable的XML文件

<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    <!--icon_vector即為要操作的VectorDrawable資源文件-->
    android:drawable="@drawable/icon_vector">
    <target
        <!--target的name,這里為上面VectorDrawable文件里的path名字-->
        android:name="icon_path"
        <!--為目標(biāo)添加的動(dòng)畫(huà)-->
        android:animation="@anim/anim_icon" />

</animated-vector>

布局中使用

<ImageView
        android:id="@+id/iv_anim"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:contentDescription="@string/app_name"
        android:src="@drawable/icon_vector_anim" />
SVG其他DEMO
1 GoogleClock
2 https://github.com/geftimov/android-pathview
3 https://github.com/mcxtzhang/PathAnimView
success.gif
SVG資源茄袖、插件推薦

1、通過(guò)iconfont獲取矢量圖

Paste_Image.png

2嘁锯、安裝svgtoandroid插件
File -> Setting -> Plugins -> Browser repositories -> 搜“svg2VectorDrawable” -> 安裝并重啟Android Studio宪祥,再次進(jìn)來(lái)后頂部工具欄會(huì)多一個(gè)圖標(biāo):


點(diǎn)擊圖標(biāo)彈出對(duì)話框:


勾選Batch選項(xiàng),將對(duì)被選中文件夾中的.svg文件進(jìn)行批量轉(zhuǎn)換家乘。nodpi會(huì)自動(dòng)添加到?jīng)]有后綴的drawable文件夾中蝗羊。

  • 手動(dòng)。新建一個(gè)<vector></vector>標(biāo)簽的xml文件仁锯,通過(guò)觀察文件內(nèi)容耀找,很容易獲取到關(guān)鍵信息。width height自然對(duì)應(yīng)<vector/>中寬高扑馁,viewBox后兩位數(shù)字是分別對(duì)應(yīng)<vector/>中的viewportWidth和viewportHeight涯呻,往下<path/>中的d的數(shù)據(jù)的對(duì)應(yīng)<vector/>中<path/>中的pathData。fillColor自己手動(dòng)設(shè)置腻要。

  • 自動(dòng)


鼠標(biāo)選中drawable文件夾复罐,右鍵, New雄家, Vector Asset效诅, Local file,然后出現(xiàn):

先選本地文件(還能支持PSD,強(qiáng)吧)乱投,再到磁盤(pán)中找到之前下載的.svg矢量圖咽笼。導(dǎo)入后可以為文件重命名(建議用svg_或者有區(qū)別于其它格式的前綴),默認(rèn)導(dǎo)入寬高均為24dp戚炫,選中Override框則讀取文件本來(lái)寬高剑刑,其它配置視需求而定。點(diǎn)擊Next到下一頁(yè)最后點(diǎn)Finish就導(dǎo)入了双肤。自動(dòng)導(dǎo)入需要格式化一下就是前面svg_ic_arrow_right.xml的樣子了施掏。

3、方法二:Android Studio的Material Icon入口
鼠標(biāo)選中drawable文件夾茅糜,右鍵七芭, New, Vector Asset蔑赘,然后出現(xiàn):

點(diǎn)擊機(jī)器人進(jìn)入搜索篩選:


左側(cè)的搜索和分類可以快速索引狸驳。這里應(yīng)該都是由谷歌官方制作的MD標(biāo)準(zhǔn)圖標(biāo),建議先到這里搜索缩赛,如果沒(méi)有再到網(wǎng)上搜索耙箍。

最后注意:

SVG:5.0以下某些機(jī)型可能會(huì)崩潰的,原因是AppCompatTextView是沒(méi)有對(duì)CompoundDrawable進(jìn)行適配的峦筒,所以我們要判斷系統(tǒng)版本如果小于5.0究西,就用ContextCompat.getDrawable獲取到Drawable實(shí)例窗慎,再setCompoundDrawablesWithIntrinsicBounds物喷。

關(guān)于適配有開(kāi)源的項(xiàng)目:
VectorCompatTextView,輕松compile到項(xiàng)目中使用遮斥。還特意添加了一個(gè)實(shí)用功能——tint
染色——可以選擇是否讓圖標(biāo)與文字顏色一樣峦失,這樣就不必關(guān)心xml里的fillColor
屬性了。用例:

<com.xw.repo.VectorCompatTextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/color_gray_light"
    android:gravity="center_vertical"
    android:padding="16dp"
    android:text="Next"
    android:textSize="16sp"
    app:drawableRightCompat="@drawable/svg_ic_arrow_right"
    app:tintDrawableInTextColor="true"/>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末术吗,一起剝皮案震驚了整個(gè)濱河市尉辑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌较屿,老刑警劉巖隧魄,帶你破解...
    沈念sama閱讀 222,729評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異隘蝎,居然都是意外死亡购啄,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)嘱么,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)狮含,“玉大人,你說(shuō)我怎么就攤上這事〖钙” “怎么了蔚龙?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,461評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)映胁。 經(jīng)常有香客問(wèn)我木羹,道長(zhǎng),這世上最難降的妖魔是什么解孙? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,135評(píng)論 1 300
  • 正文 為了忘掉前任汇跨,我火速辦了婚禮,結(jié)果婚禮上妆距,老公的妹妹穿的比我還像新娘穷遂。我一直安慰自己,他們只是感情好娱据,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布蚪黑。 她就那樣靜靜地躺著,像睡著了一般中剩。 火紅的嫁衣襯著肌膚如雪忌穿。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,736評(píng)論 1 312
  • 那天结啼,我揣著相機(jī)與錄音掠剑,去河邊找鬼。 笑死郊愧,一個(gè)胖子當(dāng)著我的面吹牛朴译,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播属铁,決...
    沈念sama閱讀 41,179評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼眠寿,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了焦蘑?” 一聲冷哼從身側(cè)響起盯拱,我...
    開(kāi)封第一講書(shū)人閱讀 40,124評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎例嘱,沒(méi)想到半個(gè)月后狡逢,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拼卵,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評(píng)論 3 342
  • 正文 我和宋清朗相戀三年奢浑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片间学。...
    茶點(diǎn)故事閱讀 40,872評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡殷费,死狀恐怖印荔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情详羡,我是刑警寧澤仍律,帶...
    沈念sama閱讀 36,533評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站实柠,受9級(jí)特大地震影響水泉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜窒盐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評(píng)論 3 336
  • 文/蒙蒙 一草则、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蟹漓,春花似錦炕横、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,700評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至嗽交,卻和暖如春卿嘲,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背夫壁。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,819評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工拾枣, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人盒让。 一個(gè)月前我還...
    沈念sama閱讀 49,304評(píng)論 3 379
  • 正文 我出身青樓梅肤,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親糯彬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子凭语,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評(píng)論 2 361

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