Android VectorDrawable与SVG

(转载)http://blog.csdn.net/xu_fu/article/details/44004841

VectorDrawable

Android L开始提供了新的API VectorDrawable 可以使用SVG类型的资源,也就是矢量图。在xml文件中的标签是<vector>,下面是一个例子

<code class="language-xml hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- res/drawable/heart.xml --></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">vector</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">xmlns:<a target=_blank href="http://lib.csdn.net/base/15" target="_blank" style="color: rgb(255, 153, 0); text-decoration: none; box-sizing: border-box;">android</a></span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"http://schemas.android.com/apk/res/android"</span>
    <!<span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">--</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">intrinsic</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">size</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">of</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">the</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">drawable</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">--</span>></span>
    android:height="256dp"
    android:width="256dp"
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- size of the virtual canvas --></span>
    android:viewportWidth="32"
    android:viewportHeight="32">

  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- draw a path --></span>
  <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">path</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:fillColor</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"#8fff"</span>
      <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:pathData</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"M20.5,9.5
                        c-1.955,0,-3.83,1.268,-4.5,3
                        c-0.67,-1.732,-2.547,-3,-4.5,-3
                        C8.957,9.5,7,11.432,7,14
                        c0,3.53,3.793,6.257,9,11.5
                        c5.207,-5.242,9,-7.97,9,-11.5
                        C25,11.432,23.043,9.5,20.5,9.5z"</span> /></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">vector</span>></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li></ul>

这样就定义好了一个静态的矢量图,可以像一般的图片资源使用,设置到imageView中会显示出一个心形。控制显示心形的就是上面path这个标签,一个path代表一个元素,绘制的内容是pathData下的一长串字符,里面是SVG绘制的一系列命令,提供moveTo、lineTo、close等操作,可以和Graphics 中的Path操作对应起来,具体可以查看SVG path Ref,后面会简要说明一下。 
VectorDrawable定义的是一张静态图,还有一个类AnimatedVectorDrawable,可以让矢量图有动画效果。一般需要三个步骤:

  • 定义VectorDrawable
<code class="language-xml hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">vector</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">xmlns:android</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"http://schemas.android.com/apk/res/android"</span>
     <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:height</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"64dp"</span>
     <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:width</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"64dp"</span>
     <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:viewportHeight</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"600"</span>
     <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:viewportWidth</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"600"</span> ></span>
     <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">group
</span>         <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"rotationGroup"</span>
         <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:pivotX</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"300.0"</span>
         <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:pivotY</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"300.0"</span>
         <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:rotation</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"45.0"</span> ></span>
         <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">path
</span>             <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"v"</span>
             <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:fillColor</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"#000000"</span>
             <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:pathData</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"M300,70 l 0,-70 70,70 0,0 -70,70z"</span> /></span>
     <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">group</span>></span>
 <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">vector</span>></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>
  • 定义AnimatedVectorDrawable,给上面矢量图的元素添加动画
<code class="language-xml hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">animated-vector</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">xmlns:android</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"http://schemas.android.com/apk/res/android"</span>
   <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:drawable</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"@drawable/vectordrawable"</span> ></span>
     <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">target
</span>         <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"rotationGroup"</span>
         <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:animation</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"@anim/rotation"</span> /></span>
     <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">target
</span>         <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"v"</span>
         <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:animation</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"@anim/path_morph"</span> /></span>
 <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">animated-vector</span>></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>
  • 定义动画文件
<code class="language-xml hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">objectAnimator
</span>     <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:duration</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"6000"</span>
     <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:propertyName</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"rotation"</span>
     <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:valueFrom</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"0"</span>
     <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:valueTo</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"360"</span> /></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>
<code class="language-xml hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">set</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">xmlns:android</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"http://schemas.android.com/apk/res/android"</span>></span>
     <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">objectAnimator
</span>         <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:duration</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"3000"</span>
         <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:propertyName</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"pathData"</span>
         <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:valueFrom</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"M300,70 l 0,-70 70,70 0,0   -70,70z"</span>
         <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:valueTo</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"M300,70 l 0,-70 70,0  0,140 -70,0 z"</span>
         <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:valueType</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"pathType"</span>/></span>
 <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">set</span>></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

由于矢量图的特点,AnimatedVectorDawable可以实现一些很特别的效果,对VectorDrawable里的pathData做动画,可以从一个图形渐变到另一个图形,比如Material Design里的toolbar icon;对trimPathStart、trimPathEnd做动画,可以得到图形的绘制轨迹。

SVG Path Data

主要有以下一些命令

  • M: move to 移动绘制点
  • L:line to 直线
  • Z:close 闭合
  • C:cubic bezier 三次贝塞尔曲线
  • Q:quatratic bezier 二次贝塞尔曲线
  • A:ellipse 圆弧

每个命令都有大小写形式,大写代表后面的参数是绝对坐标,小写表示相对坐标。参数之间用空格或逗号隔开

命令详解:

  • M (x y) 移动到x,y
  • L (x y) 直线连到x,y,还有简化命令H(x) 水平连接、V(y)垂直连接
  • Z,没有参数,连接起点和终点
  • C(x1 y1 x2 y2 x y),控制点x1,y1 x2,y2,终点x,y
  • Q(x1 y1 x y),控制点x1,y1,终点x,y
  • A(rx ry x-axis-rotation large-arc-flag sweep-flag x y) 
    rx ry 椭圆半径 
    x-axis-rotation x轴旋转角度 
    large-arc-flag 为0时表示取小弧度,1时取大弧度 
    sweep-flag 0取逆时针方向,1取顺时针方向 
    有个图解: 

应用

在github上看到一个VectorDrawable应用的例子,实现了一个动态效果的searchbar,原理就是对VectorDrawable trimPathStart这个属性做动画。最初的设计在这里,照着实现一下:

Reference


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android SVG (Scalable Vector Graphics) 是一种用于在 应用程序中显示可缩放矢量图形的格式。SVG 图像使用 XML 语法进行描述,可以无损地缩放和放大,而不会失去清晰度和质量。 Android 提供了一些方法来在应用程序中加载和显示 SVG 图像。最常用的方法是使用第三方库,例如 AndroidSVGSvg-androidAndroidSVG Library。这些库提供了用于解析和渲染 SVG 图像的类和方法。 要在 Android 应用程序中使用 SVG 图像,首先需要将 SVG 文件保存在项目的资源文件夹中。然后,可以使用相应的库来加载和显示 SVG 图像。通常,需要将 SVG 图像转换为 Android 可以理解和显示的格式,例如 Bitmap 或 Drawable。 以下是一个简单的示例代码,演示如何使用 AndroidSVG 库加载和显示 SVG 图像: ```java import com.caverock.androidsvg.SVG; import com.caverock.androidsvg.SVGParseException; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Picture; import android.graphics.drawable.PictureDrawable; import android.widget.ImageView; public void loadSvgImage(Context context, ImageView imageView, int svgResId) { try { SVG svg = SVG.getFromResource(context, svgResId); Picture picture = svg.renderToPicture(); PictureDrawable drawable = new PictureDrawable(picture); imageView.setImageDrawable(drawable); } catch (SVGParseException e) { e.printStackTrace(); } } ``` 在上面的示例中,`loadSvgImage` 方法接收一个上下文对象、一个 ImageView 和一个指向 SVG 文件的资源 ID。它使用 AndroidSVG 库从资源中加载 SVG 图像,并将其渲染为 PictureDrawable,然后将其设置为 ImageView 的图像。 这只是一个基本示例,你可以根据自己的需求进行更多的定制和扩展。希望这能帮助你开始在 Android 应用程序中使用 SVG 图像!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值