Android SVG的使用

一、背景

由于android 碎片化严重,对于不同型号手机、不同屏幕分辨率的适配,就显得异常艰难了。一般的做法是切好几套分辨率的图来保证拉伸不会出现太大的问题,虽说多几套图可以基本解决适配的问题,但是会造成安装包的体积增大,同时一些不常见的设备上也容易出现变形的问题,Android Vector 的出现可以解决此问题。

二、什么是svg

  • SVG 意为可缩放矢量图形(Scalable Vector Graphics)
  • SVG 使用 XML 格式定义图形,运行的时候才会去通过一些特定的语法和规则渲染绘制出图像
  • 图像在放大或改变尺寸的情况下其图形质量不会有所损失
  • SVG 是万维网联盟的标准,与诸如 DOM 和 XSL 之类的 W3C 标准是一个整体,用来定义用于网络的基于矢量的图形
  • 可以直接用 编写 XML 来描绘图片,使图片具有很强的交互性

注:svg目前在网页端被广泛的使用,android 中是通过什么来实现的呢 ?google 提供了VectorDrawable和AnimatedVectorDrawable两个类来实现svg ,也即是Vector 就是SVG 在android 中的实现,从android 5.0开始支持,google也从AppCompat23.2 版本提供了对低版本svg 的兼容。

svg更详细的介绍和用法请参照w3 School连接,请点我
Android vector 更细的介绍和用法请参照google网站api 请点我

三、矢量图和位图

位图:是由像素点组合而成的图像,一个点就是一个像素,每个点都有自己的颜色。位图和分辨率有着直接的联系,分辨率大的位图清晰度高,其放大倍数也相应增加。但是,当位图的放大倍数超过其最佳分辨率时,就会出现细节丢失,并产生锯齿状边缘的情况。像平时移动端用的比较多的png格式的图片就是位图

矢量图:是以数学向量方式记录图像的,其内容以线条和色块为主。矢量图和分辨率无关,它可以任意地放大且清晰度不变,也不会出现锯齿状边缘,本文要讲的svg就是矢量图

四、Android 使用svg 的优势和劣势

  • 优势
    • SVG 可被非常多的工具读取和修改(比如记事本)
    • SVG 与 JPEG 和 GIF 图像比起来,尺寸更小,且可压缩性更强。
    • SVG 是可伸缩的
    • SVG 图像可在任何的分辨率下被高质量地打印
    • SVG 可在图像质量不下降的情况下被放大
    • SVG 图像中的文本是可选的,同时也是可搜索的(很适合制作地图)
    • SVG 可以与 Java 技术一起运行
    • SVG 是开放的标准
    • SVG 文件是纯粹的 XML
    • 它最主要优点就是不会降低图片质量的前提下,可以适应所有分辨率屏幕
    • 方便实现很多优美的动画效果
  • 劣势:
    • Vector是Android 5.0 之后才出来的,从 AppCompat23.2 开始支持5.0版本以下使用Vector。部分设备兼容有问题
    • Android Vector Drawable 并不支持所有 SVG 的语法,例如需要将网页中的svg图片转化到Android Vector时,不成功,此时需要修改部分属性才可使用,但支持的语法已经足够使用。
    • 运行时才绘制,效率不高

五、如何使用

1、语法

VectorDrawable 使用 <vector>元素在XML 中定义,代码如下

 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:height="64dp"
     android:width="64dp"
     android:viewportHeight="600"
     android:viewportWidth="600" >
     <group
         android:name="rotationGroup"
         android:pivotX="300.0"
         android:pivotY="300.0"
         android:rotation="45.0" >
         <path
             android:name="v"
             android:fillColor="#000000"
             android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
     </group>
 </vector>

Vector属性

  • <vector> 用于定义一个可绘制的矢量图
    • android:name 矢量图的名称
    • android:width 用于定义drawable的内在宽度。这支持所有尺寸单位,通常用dp指定
    • android:height 用于定义drawable的内在高度。这支持所有尺寸单位,通常用dp指定
    • android:viewportWidth 用于定义视图空间的宽度,即虚拟画布的宽度
    • android:viewportHeight于定义视图空间的高度,即虚拟画布的高度
    • android:tint 作为色彩应用于绘图的颜色,默认不着色
    • android:tintMode Porter-Duff混合模式用于色调颜色。默认是src_in。
    • android:autoMirrored 指示绘图窗口的布局方向为RTL(从右到左)时是否需要镜像。默认为false。
    • android:alpha drawable的不透明度。默认值是1.0。

group

  • **<group> 定义一组路径或子组,以及转换信息。用于缩放、旋转、位移
    • android:name 组名称
    • android:rotation 组的旋转角度,默认为0
    • android:pivotX 组的缩放和旋转的枢轴的X坐标,默认为0
    • android:pivotY 组的缩放和旋转的枢轴的Y坐标,默认为0
    • android:scaleX X坐标上的缩放量,默认为1
    • android:scaleY Y坐标上的缩放量,默认为1
    • android:translateX X坐标上的平移量,默认为0
    • android:translateY Y坐标上的平移量,默认为0

Path

  • <path> 定义绘制的路径
    • android:name ,路径名称
    • android:pathData ,路径
      • M = moveto (M X,Y) ,将画笔移动到指定的坐标位置
      • L = lineto(L X,Y) ,画直线到指定的坐标位置
      • H = horizontal lineto (H X) ,画水平线到指定的X坐标位置
      • V = vertical lineto (V Y) ,画垂直线到指定的Y坐标位置
      • C = curveto(C X1,Y1,X2,Y2,ENDX,ENDY) ,:三次贝赛曲线
      • S = smooth curveto(X2, Y2, X ,Y) ,光滑三次贝塞尔曲线
      • Q = quadratic Belzier curve (Q X,Y,ENDX,ENDY),二次贝赛曲线
      • T = smooth quadratic Belzier curveto (T ENDX,ENDY) ,映射
      • A = elliptical Arc(A RX,RY,XROTATION,FLAG1,FLAG2,X,Y) ,弧线
      • Z = closepath (Z) ,关闭路径
        注释:以上所有命令均允许小写字母。大写表示绝对定位,小写表示相对定位。
    • android:fillColor 指定用于填充路径的颜色。可以是颜色,或者对于SDK 24+,可以是颜色状态列表或渐变颜色(请参阅GradientColorGradientColorItem)。如果此属性为动画,则由动画设置的任何值都将覆盖原始值。如果未指定此属性,则不绘制路径填充。
    • android:strokeColor 指定用于绘制路径轮廓的颜色。可以是颜色,或者对于SDK 24+,可以是颜色状态列表或渐变颜色(请参阅GradientColorGradientColorItem)。如果此属性为动画,则由动画设置的任何值都将覆盖原始值。如果未指定此属性,则不绘制路径轮廓。
    • android:strokeWidth 路径行程的宽度。缺省值是0
    • android:strokeAlpha 路径笔画的不透明度。缺省值是1。
    • android:fillAlpha 不透明度填补路径。缺省值是1。
    • android:trimPathStart 要从头开始修剪的路径的分数,范围从0到1.默认值为0。
    • android:trimPathEnd 从末尾修剪的路径的分数,范围从0到1.默认值为1。
    • android:trimPathOffset 移位修剪区域(允许显示的区域包括开始和结束),范围从0到1.默认值为0。
    • android:strokeLineCap 设置描边路径的线条:对接,圆形,方形。默认是对接。
    • android:strokeLineJoin 设置描边路径的lineJoin:斜角,圆形,斜角。缺省是斜角。
    • android:strokeMiterLimit 设置描边路径的斜接限制。缺省值是4

clip-path

  • <clip-path> 定义路径为当前剪辑。请注意,剪辑路径仅适用于当前组及其子组。
    • android:name定义剪辑路径的名称
    • android:pathData 使用与SVG路径数据中 path数据来定义

2、简单实例:

这里我们以网页 使用的svg图片来生成android 中的svg图片来说明,为什么不直接使用VectorDrawable 的元素及其属性来生成svg呢?
因为我们要使用上述讲解的各个元素及属性生成,是极其复杂的,作为程序员不应该把时间学浪费到上面,只需看懂即可
我们可以通过svg编辑软件生成svg图片,或者UI提供好的svg 图片转化为android 可以使用的格式,即在已有资源的基础上进行改进,效率会更高

1.将下面xml 代码用.svg的文件保存,命名为test.svg


<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg width="100%" height="100%" version="1.1"
xmlns="http://www.w3.org/2000/svg">

<circle cx="50" cy="50" r="40" stroke="black"
stroke-width="2" fill="red"/>

</svg>

2.用支持svg的浏览器打开(如chrome)


test.png

3.转化为android 中可以使用的xml,这里使用到了android studio 中的Vector Asset ,如下图:


QQ截图20180301070923.png

4.选择Local file(SVG,PSD),设置本地路径,修改文件名、大小等即可将上述网页中使用的svg,转化为android 中使用的svg 图片
QQ截图20180301072015.png

5.转化后的svg代码如下:

<vector android:height="24dp" android:viewportHeight="100.0"
    android:viewportWidth="100.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
    <path android:fillColor="#ff0000"
        android:pathData="M50,50m-40,0a40,40 0,1 1,80 0a40,40 0,1 1,-80 0"
        android:strokeColor="#000000" android:strokeWidth="2"/>
</vector>
  1. 布局文件和代码中使用vector 图片
  • 布置文件


    result.png
  • 代码中

ImageView iv = findViewById(R.id.iv);
iv.setImageResource(R.drawable.ic_test);

可以看出和位图 png 格式的图片使用基本一致~

3.动画

动画施工ing

六、结语

Vector的出现对开发者来说是一大福音,可能在某些低版本还是会存在兼容性问题,但我们可以尝试在一些不太重要的功能上先使用,积累经验,当某一天,我们不需要考虑低版本系统,或者低版本的兼容库已经做的非常强大的时候,或许svg 会替代目前使用的位图(png)也说不一定。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容