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
SVG資源茄袖、插件推薦
1、通過(guò)iconfont獲取矢量圖
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"/>