SVG前戏—让你的View多姿多彩

849 阅读6分钟

什么是SVG

SVG的全称是Scalable Vector Graphics,叫可缩放矢量图形。是一种基于可扩展标记语言(XML)。它和位图(Bitmap)相对,SVG不会像位图一样因为缩放而让图片质量下降。它的优点在于节约空间,使用方便。

svg的优点

首先简要解释一下矢量图像格式和位图图像格式的区别。矢量图像用点和线来描述物体,所以文件会比较小,同时也能提供高清晰的画面,适合于直接打印或输出。而位图图像的存储单位是图像上每一点的像素值,因此一般的图像文件都很大,会占用大量的网络带宽。SVG是一种矢量图形格式,GIF、JPEG是光栅文件格式。有了两者的概念后,SVG较GIF、JPEG的优势显而易见。

  • SVG 可被非常多的工具读取和修改(比如记事本)
  • SVG 与 JPEG 和 GIF 图像比起来,尺寸更小,且可压缩性更强。
  • SVG 是可伸缩的
  • SVG 图像可在任何的分辨率下被高质量地打印
  • SVG 可在图像质量不下降的情况下被放大
  • SVG 图像中的文本是可选的,同时也是可搜索的(很适合制作地图)
  • SVG 可以与 Java 技术一起运行
  • SVG 是开放的标准
  • SVG 文件是纯粹的 XML
  • svg格式相对于.jpg、.png甚至.webp可以 省时间和 省空间

推荐项目学习地址

github.com/geftimov/an…

使用方法:

svg是在Android于5.0版本将该特性引入(Lollipop, API 21)。今天我们就讨论 一下在5.0以上版本中使用方法。

1)生成svg

1、可以找美工用PS或者是AI设计成图片后利用第三方工具进行转化为svg,以便我们能方便拿到svg数据

2、利用 Android Studio 具动态生成位图,Studio内置一个名为 Vector Asset Studio 的工具,在低版本SDK上编译APK期间,针对VectorDrawable脚本自动生成一组PNG位图资源BitmapDrawable,取代矢量图形(在5.0及以后的手机上运行时会正常引用VectorDrawable)。

需要配置build.gradle:

defaultConfig {
    vectorDrawables.generatedDensities = ['hdpi','xxhdpi']
}
2)将普通SVG图片数据转换成Android可用数据

一般的SVG图片数据是直接在html或jsp中可以使用,对我们android开发者来讲是要 拿到svg.xml的资源的,我们可以使用NotPad++打开,查看源码

解析SVG数据

我们知道,svg是以xml数据格式来进行描述的,既然svg本质上就是xml文件,所以从解析角度来看,能解析xml文件的工具应该几乎都可以用来解析svg文件。

1、DOM解析 查看Android源码可以看出,5.0引入svg后并没有使用dom进行解析svg源文件,虽然svg号称完全支持dom标准。笔者从dom解析的过程可以看出,Dom解析是将xml文件全部载入,组装成一颗dom树,然后通过节点以及节点之间的关系来解析xml文件。虽然一般情况下,svg文件是比较小的,但也不乏有些很复杂的图片会上升到M级别,如果在解析时需要全部载入,对于Android系统来说时比较耗时的,这也许就是dom遭Android淘汰的原因之一吧。 2、SAX解析 SAX(Simple API for XML)解析器是一种基于事件的解析器,它的核心是事件处理模式,主要是围绕着事件源以及事件处理器来工作的。当事件源产生事件后,调用事件处理器相应的处理方法,一个事件就可以得到处理。在事件源调用事件处理器中特定方法的时候,还要传递给事件处理器相应事件的状态信息,这样事件处理器才能够根据提供的事件信息来决定自己的行为。SAX解析器的优点是解析速度快,占用内存少。非常适合在Android移动设备中使用 3、PUll解析 PULL解析器的运行方式和SAX类似,都是基于事件的模式。不同的是,在PULL解析过程中,我们需要自己获取产生的事件然后做相应的操作,而不像 SAX那样由处理器触发一种事件的方法,执行我们的代码。PULL解析器小巧轻便,解析速度快,简单易用,非常适合在Android移动设备中使 用,Android系统内部在解析各种XML时也是用PULL解析器

一般这种方式我们只有自定义View进行解析

创建View,开启线程,进行解析,可以自己自己的需求进行绘制和加载相应的动画

布局中正常加载View一样加载解析出来的svg

备注如果对于简单的已有svg的 vectordrawable.xml,直接可以如对ImageView设置背景动画

<?xml version="1.0" encoding="utf-8"?>
<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>

 <?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/vectordrawable">
    <target
        android:name="rotationGroup"
        android:animation="@animator/rotation" />
    <target
        android:name="v"
        android:animation="@animator/path_morph" />
</animated-vector>
Drawable drawable = iv.getDrawable();
if (drawable instanceof Animatable) {
            Animatable able = (Animatable) drawable;
            able.start();
}

这种方式可以帮助我们解决用原生实现起来比较麻烦的一些特殊的需求。

多边形

六边形控件

使用SVG需要注意的是

一、SVG是在Android 5.0之后才支持的,所以如果想支持5.0之前的版本,最好使用兼容库。具体使用如下:

在build.gradle的defaultConfig中添加

vectorDrawables.useSupportLibrary = true

二、继承AppCompatActivity

Activity也需要继承AppCompatActivity

另外:如果想在Activity代码中动态设置SVG(VectorDrawable), 需要动态添加兼容

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);

三、显示问题

1、 UI给的SVG图片应该显示的是白色,但是在Android设备上显示的确实黑色 2、 在某些手机上SVG会出现锯齿,给用户造成的感觉就是字体style都不一样

一般情况下UI给我们的SVG图片可能需要我们手动的修改一下,比如我们需要将fillColor改为“#FFFFFFFF”这样字体才能显示为白色。并且需要将width和height设置为120dp,否则会有锯齿

SVG的不足之处

矢量图的优点一大把,但也不是万能的。矢量图特别适合icon图标的应用场景,但是不能用于比如加载相册时,设置的placeholder或者error这类需要频繁切换回收的应用场景,否则会造成非常明显的卡顿,因为矢量图是不被硬件加速支持的。

下期预告<<用SVG打造一个绚丽多彩的中国地图>>

阅读更多

近3年BAT面试真题整理合集

一招教你读懂JVM和Dalvik之间的区别

NDK项目实战—高仿360手机助手之卸载监听

分享几个Android很强势的的开源框架

相信自己,没有做不到的,只有想不到的

在这里获得的不仅仅是技术!

技术+职场