Andrid5.0新特性——SVG(可缩放矢量图形)

什么是SVG(Scalable Vector Graphics

SVG一种用于描述图像的标记语言。类似HTML。

SVG严格遵从XML语法,并用文本格式的描述性语言来描述图像内容,因此是一种和图像分辨率无关的矢量图形格式。

标准制定开发历史

  • 2001年9月4日,发布SVG 1.0。
  • 2003年1月4日,发布SVG 1.1。
  • 2003年1月14日,推出SVG移动子版本:SVG Tiny和SVG Basic。
  • 2008年12月22日,发布SVG Tiny 1.2。
  • 2011年8月16日,发布SVG 1.1(第2版),成为W3C目前推荐的标准。
  • W3C目前仍正在研究制定SVG2,目前最新的草稿发布见

示例

下面是一个红色三角形的svg示例:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="4cm" height="4cm" viewBox="0 0 400 400"
     xmlns="http://www.w3.org/2000/svg" version="1.1">
  <title>Example triangle01- simple example of a ‘path‘</title>
  <desc>A path that draws a triangle</desc>
  <rect x="1" y="1" width="398" height="398"
        fill="none" stroke="blue" />
  <path d="M 100 100 L 300 100 L 200 300 z"
        fill="red" stroke="blue" stroke-width="3" />
</svg>

效果图如下:

说明:

  • svg矢量图的根节点就是svg,包含图片宽高和视口大小等信息。
  • rect表示一个矩形。
  • path(点击查看path元素介绍)表示一条路径,矢量图的形状就是通过path元素定义的,常见属性有:
    • M (x y)+:在给定的(x,y)坐标开始path;
    • L (x y)+:绘制一条直线从当前点到给定的(x,y)坐标;
    • z:闭合当前path。
    • C (x1 y1 x2 y2 x y)+:贝塞尔曲线;

点击查看svg元素索引列表

用SVG有什么好处

  • svg是矢量图,缩放不会失真,位图缩放可能产生失真问题。
  • 屏幕适配方便,一般我们为了适配不同分辨率可能会在ldpi、mdpi、hdpi、xhdpi等目录放对应分辨率的jpg/png图片,现在只需要一个xml文件,而且xml文件比jpg/png体积小,有利于缩减apk体积。

SVG相关工具

在Android中使用SVG

创建矢量图片(VectorDrawable

在Android中,负责矢量图加载,解析,绘制相关工作的类就是VectorDrawable,通过加载一个基于XML的VectorDrawable文件,在draw方法中把矢量图绘制到Canvas。在Android中矢量图一般用于图标和按钮。

1.这里使用Method Draw先编辑一个svg格式的矢量图,点击打开Method Draw,编辑完成后导出svg格式文件。

heart.svg

<svg height="400" width="580" xmlns="http://www.w3.org/2000/svg">
    <!-- Created with Method Draw - http://github.com/duopixel/Method-Draw/ -->
    <g stroke="null">
        <title>Layer 1</title>
        <path d="m218.25,65.499992c31.171158,0 61.067017,21.318344 71.75,50.4375c10.683014,-29.119156 40.610474,-50.4375 71.75,-50.4375c40.546692,0 71.75,32.481865 71.75,75.656258c0,59.348114 -60.477264,105.195892 -143.5,193.34375c-83.022751,-88.131226 -143.5,-133.995636 -143.5,-193.34375c0,-43.174393 31.203293,-75.656258 71.75,-75.656258z" fill="#ff0000"
            id="svg_1"
            stroke="#ff0000" stroke-width="1.5" />
    </g>
    <g>
        <title>background</title>
        <rect fill="none" height="402" id="canvas_background" width="582" x="-1" y="-1" />
    </g>
</svg>

2.把svg文件转换为Android的VectorDrawable文件。

  • 手动转换

    1. 在drawable目录下新建一个根节点为<vector>的xml文件。

    2. 把svg文件中的path数据拷贝到<vector>,比如svg中path的d对应<vector>中path的android:pathData,stroke对应android:strokeColor,stroke-width对应android:strokeWidth等。

  • 使用工具转换

    使用svg2android把svg文件转换为Android Drawable文件,把导出文件放到drawable目录下。

res/drawable/vector_drawable_heart.xml

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    <!-- 图片实际宽高 -->
    android:width="580dp"
    android:height="400dp"
    <!-- 画布的宽高,图像的锚点、坐标都是相对于画布 -->
    android:viewportWidth="580"
    android:viewportHeight="400">

    <!-- draw a path -->
    <path
        android:fillColor="#ff0000"
        android:pathData="M218.25,65.499992c31.171158,0 61.067017,21.318344
71.75,50.4375c10.683014,-29.119156 40.610474,-50.4375 71.75,-50.4375c40.546692,0
71.75,32.481865 71.75,75.656258c0,59.348114 -60.477264,105.195892
-143.5,193.34375c-83.022751,-88.131226 -143.5,-133.995636
-143.5,-193.34375c0,-43.174393 31.203293,-75.656258 71.75,-75.656258z"
        android:strokeColor="#ff0000"
        android:strokeWidth="1.5" />

    <path android:pathData="M -1 -1 H 581 V 401 H -1 V -1 Z" />

</vector>

注意:转换工具默认把画布的size作为矢量图的实际宽高,比如一个icon的svg设计时画布的宽高为480*480,但实际需要的宽高为48*48,所以记得修改<vector>中的android:widthandroid:height为实际需要的宽高,不然就比较耗内存。

3.使用矢量图示例

<ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/vector_drawable_heart" />

目前这种做法只支持Android5.0+,如果想在Android5.0以下正常运行还要做如下兼容处理。

VectorDrawable向下兼容

1.在app的build.gradle文件中添加如下配置,启用support库。

android {
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }
}

dependencies {
    compile ‘com.android.support:appcompat-v7:23.3.0‘
}

2.ImageView改为使用support库的AppCompatImageView,使用app:srcCompat替换android:src

<android.support.v7.widget.AppCompatImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:srcCompat="@drawable/vector_drawable_heart" />

为矢量图片添加动画(AnimatedVectorDrawable

AnimatedVectorDrawable可以让VectorDrawable加上动画效果。

VectorDrawable实现动画效果一般需要3个文件:

  • VectorDrawable文件,根节点为<vector>的xml文件,矢量图。
  • AnimatedVectorDrawable文件,根节点为<animated-vector>的xml文件,矢量图动画定义文件。
  • 一个或多个属性动画文件。

1.VectorDrawable文件如下,通过android:name属性为group和path定义了一个唯一的名字,在AnimatedVectorDrawable文件中就是通过该名字实现group/path和相关动画的关联。

<!--res/drawable/vector_drawable_cpu.xml-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="128dp"
    android:height="128dp"
    android:viewportHeight="600"
    android:viewportWidth="600">

    <group android:name="cpu_box">
        <path
            android:name="cpu"
            android:fillColor="#000000"
            android:pathData="
            M341.087,157.478 c7.417,0,13.435,6.018,13.435,13.435 v170.174c0,7.417-6.018,13.435-13.435,13.435 H170.913 c-7.417,0-13.435-6.018-13.435-13.435V170.913c0-7.417,6.018-13.435,13.435-13.435H341.087z
            M390.348,157.478 c0-19.785-16.041-35.826-35.826-35.826H157.479c-19.785,0-35.826,16.041-35.826,35.826v197.043 c0,19.785,16.041,35.826,35.826,35.826h197.043c19.785,0,35.826-16.041,35.826-35.826V157.478z " />
    </group>
    <group android:name="bottom">
        <path
            android:name="wires_bottom"
            android:fillColor="#000000"
            android:pathData="
        M193.304,408.261V462h-17.913 v-53.739H193.304z
        M264.957,408.261V462h-17.914v-53.739H264.957z
        M300.783,408.261V462h-17.914v-53.739H300.783z
        M229.13,408.261 V462h-17.913v-53.739H229.13z
        M336.609,408.261V462h-17.914v-53.739H336.609z" />
    </group>
    <group android:name="top">
        <path
            android:name="wires_top"
            android:fillColor="#000000"
            android:pathData="
        M193.304,50v53.739h-17.913V50H193.304z
        M264.957,50 v53.739h-17.914V50H264.957z
        M300.783,50v53.739h-17.914V50H300.783z
        M229.13,50v53.739h-17.913V50H229.13z
        M336.609,50v53.739 h-17.914V50H336.609z " />
    </group>
    <group android:name="right">
        <path
            android:name="wires_right"
            android:fillColor="#000000"
            android:pathData="
        M408.261,318.695H462v17.914h-53.739V318.695z
        M408.261,247.043H462v17.914h-53.739V247.043z
        M408.261,211.217 H462v17.913h-53.739V211.217z
        M408.261,282.869H462v17.914h-53.739V282.869z
        M408.261,175.391H462v17.913h-53.739V175.391z" />
    </group>
    <group android:name="left">
        <path
            android:name="wires_left"
            android:fillColor="#000000"
            android:pathData="
        M50,318.695h53.739v17.914H50V318.695z
        M50,247.043h53.739v17.914H50V247.043z
        M50,211.217h53.739v17.913H50V211.217z
        M50,282.869 h53.739v17.914H50V282.869z
        M50,175.391h53.739v17.913H50V175.391z" />
    </group>

</vector>

效果图如下:

2.属性动画文件的编写,下面是cpu顶部排线的动画文件,还有类似的底部和左右排线的动画文件,共4个动画文件。

<!-- res/animator/pulse_top.xml -->
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:propertyName="translateY"
        android:valueType="floatType"
        android:valueFrom="0"
        android:valueTo="-10"
        android:repeatMode="reverse"
        android:repeatCount="infinite"
        android:duration="250" />
</set>

3.AnimatedVectorDrawable文件如下,根节点<animated-vector>,通过android:drawable属性设置使用的矢量图文件。<target>元素中的android:name对应VectorDrawable文件中group/path的名称,android:animation设置group/path使用的动画。

<!-- res/drawable/animated_cpu.xml -->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/vector_drawable_cpu">

    <target
        android:name="top"
        android:animation="@animator/pulse_top" />

    <target
        android:name="right"
        android:animation="@animator/pulse_right" />

    <target
        android:name="left"
        android:animation="@animator/pulse_left" />

    <target
        android:name="bottom"
        android:animation="@animator/pulse_bottom" />

</animated-vector>

4.最后,在AppCompatImageView中使用AnimatedVectorDrawable

  • 在xml中使用AnimatedVectorDrawable:
<android.support.v7.widget.AppCompatImageView
        android:id="@+id/image1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        app:srcCompat="@drawable/animated_cpu" />
  • 在代码中使用AnimatedVectorDrawable:

使用AnimatedVectorDrawableCompat.create方法加载AnimatedVectorDrawable文件得到AnimatedVectorDrawable对象。

AnimatedVectorDrawableCompat是support库中的类,作用是使AnimatedVectorDrawable兼容Android5.0以下系统。

    image1 = (AppCompatImageView) findViewById(R.id.image1);
    AnimatedVectorDrawableCompat animatedVectorDrawable = AnimatedVectorDrawableCompat.create(this, R.drawable.animated_cpu);
    image1.setImageDrawable(animatedVectorDrawable);
    addClickAnimationListener(image1);

点击停止/播放动画

public void addClickAnimationListener(final AppCompatImageView image) {
        image.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Drawable animation = image.getDrawable();
                if (animation instanceof Animatable) {
                    Animatable anim = (Animatable) animation;
                    if (anim.isRunning()) {
                        // 停止动画
                        anim.stop();
                    } else {
                        // 播放动画
                        anim.start();
                    }
                }
            }
        });
    }

动画效果如下:

注意:目前AnimatedVectorDrawableCompat在Android5.0以下不支持pathData类型属性动画。如果需要用到pathData类型属性动画可以通过以下方法做兼容处理。

  • 使用api标识符适配不同版本的系统,在drawable和drawable-v21目录下定义不同的实现。
  • 代码中作兼容处理
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
    // 在android5.0+下执行下面代码
}
  • 使用vector-compat,VectorDrawable和AnimatedVectorDrawable的一个兼容库。

透明度,旋转,缩放属性动画没有效果?

这里给VectorDrawable的path添加一个透明度动画,发现没有效果,日志打印如下:

W/PropertyValuesHolder: Method setAlpha() with type int not found on target class class android.support.graphics.drawable.VectorDrawableCompat$VGroup
W/PropertyValuesHolder: Method setRotation() with type float not found on target class class android.support.graphics.drawable.VectorDrawableCompat$VFullPath

日志中可以看出没有找到相关的set方法,属性动画的实现原理其实是通过java中的反射找到相关set方法去动态修改属性值实现的。

VectorDrawable(这里使用的是VectorDrawableCompat,兼容Android5.0以下版本)的group对应的类是VectorDrawableCompat$VGroup,path对应的类是VectorDrawableCompat$VFullPath

通过查看VectorDrawableCompat$VFullPath代码发现,VFullPath中透明度属性的名称为fillAlpha,于是把android:propertyName值由alpha改为fillAlpha就可以了。

<objectAnimator
        android:duration="1500"
        android:propertyName="fillAlpha"
        android:valueFrom="1"
        android:valueTo="0"
        android:valueType="floatType" />

示例代码工程地址:https://coding.net/u/linchaolong/p/AndroidSvgExample/git

相关开源项目

vector-compat

VectorDrawable和AnimatedVectorDrawable的一个兼容库,目前支持api 14+。

Github地址:https://github.com/wnafee/vector-compat

点击查看详细介绍

AndroidSVG

AndroidSVG是Android下的SVG解析、渲染库。目前几乎完全支持SVG 1.1的静态可视元素和SVG 1.2小部分规范(filters除外)。支持API 8+。

支持svg格式矢量图的ImageView

<com.caverock.androidsvg.SVGImageView
    xmlns:svg="http://schemas.android.com/apk/res-auto"
    android:layout_width="100dp"
    android:layout_height="50dp"
    svg:svg="filename.svg"/>

android-pathview

android-pathview是绘制路径的动画库,路径可来自于svg或者标准Paths,使svg或path具有动画效果,并且可以改变路径的颜色、宽度。

Github地址:https://github.com/geftimov/android-pathview

点击查看详细介绍

vectalign

Android4.4以后AnimatedVectorDrawable可以让两个SVG图像无缝过渡(称为变形动画),但是这两个svg图像的path必须参数个数要相等,同时这些参数的类型要匹配(也就是说格式要对齐),如果不对齐会产生异常。简单的path可以手动修改对齐,但是复杂点的就比较难了。这个工具就是通过命令行的方式将任意两个svg资源转换成对齐的模式,而不会改变原始图像的外观。

Githu地址:https://github.com/bonnyfone/vectalign

点击查看详细介绍

素材分享

时间: 2024-10-22 14:21:32

Andrid5.0新特性——SVG(可缩放矢量图形)的相关文章

Day07 jdk5.0新特性&Junit&反射

day07总结 今日内容 MyEclipse安装与使用 JUnit使用 泛型 1.5新特性 自动装箱拆箱 增强for 静态导入 可变参数方法 枚举 反射 MyEclipse安装与使用(yes) 安装MyEclipse 先安装了JDK ? MyEclipse介绍 ? MyEclipse是Eclipse的一个插件: MyEclipse是需要花钱的: MyEclipse官网不在欢迎中国人登录: ? MyEclipse使用 ? 1 创建项目 选择工作空间: 工作空间路径不能有空格和中文: 工作空间以班名

Atitit.&#160;C#.net&#160;clr&#160;2.0&#160;&#160;4.0新特性

Atitit. C#.net clr 2.0  4.0新特性 1. CLR内部结构1 2. CLR 版本发展史3 3. CLR 2.0 3 4. CLR 4 新特性 概览4 4.1.1.  托管与本地代码的互操作5 4.1.2.    垃圾回收6 4.1.3.    代码约定6 4.1.4.    Corrupted state exception6 4.1.5.     新的安全模型7 4.1.6.     同一个进程,多个CLR7 4.1.7.     基本类库7 5. CLR最新发展8 6

day07 MyEclipse 安装 jdk5.0 新特性

1.myeclipse的安装和使用 * eclipse:是一个免费的开发工具    * myeclipse:是一个收费的插件,破解myeclipse,        ** 安装目录的要求: 不能有中文和空格        ** 安装完成之后,选择一个工作空间 ,这个工作空间不能有中文和空格    * 破解myeclipse        ** 运行run.bat文件,但是运行之前,必须要安装jdk,通过配置环境变量 * myeclipse的使用        * 创建一个工程          

AFNetworking 2.0 新特性讲解之AFHTTPSessionManager

AFNetworking 2.0 新特性讲解之AFHTTPSessionManager (2014-02-17 11:56:24) 转载▼     AFNetworking 2.0 相比1.0 API 接口改动还是很大的. 其中一个便是 AFURLSessionManager,当然如果你不太熟悉,或者为了兼容低版本,你依然可以选择AFHTTPRequestOperationManager,AFURLSessionManager是基于 NSURLSessionConfiguration(IOS 7

Servlet 3.0 新特性详解

转自:https://www.ibm.com/developerworks/cn/java/j-lo-servlet30/ Servlet 3.0 新特性详解 张 建平2010 年 4 月 23 日发布 WeiboGoogle+用电子邮件发送本页面 6 Servlet 3.0 新特性概述 Servlet 3.0 作为 Java EE 6 规范体系中一员,随着 Java EE 6 规范一起发布.该版本在前一版本(Servlet 2.5)的基础上提供了若干新特性用于简化 Web 应用的开发和部署.其

android 7.0 新特性 和对开发者的影响

android 7.0新特性 - jiabailong的专栏 - 博客频道 - CSDN.NEThttp://blog.csdn.net/jiabailong/article/details/52411300 android 7.0对开发者会有哪些影响 - jiabailong的专栏 - 博客频道 - CSDN.NEThttp://blog.csdn.net/jiabailong/article/details/52411353 android 7.0 多窗口及新特性demo - jiabail

C#6.0新特性

C#6.0新特性怎么用 系列文章 Visual Studio 2015速递(1)——C#6.0新特性怎么用 前文提到过一个神器叫Resharper,功能强大,编码效率和代码质量那是蹭蹭的涨,但是神器的最大问题是太耗费资源了,每次系统提示内存不足的时候,那叫一个纠结啊.因此每次新的VS发布的时候都情不自禁的查看是否增强编辑功能,情不自禁的讨论一番,这次VS2015也不例外. 去年微软放出Roslyn的时候,微软就曾经放出过一个“尝鲜”版的VS编辑增强功能,恰恰就是重构(reflector),话说这

ASP.NET MVC—1、前期知识储备(C#3.0新特性)

在学习ASP.NET MVC之前,有必要先了解一下C#3.0所带来的新的语法特性,这一点尤为重要,因为在MVC项目中我们利用C#3.0的新特性将会大大的提高我们的开发效率,同时,在MVC项目中你将到处可以看到C#3.0新特性的身影. C#3.0新特性 自动属性 隐式类型 var 对象初始化器与集合初始化器 匿名类 扩展方法 Lambda表达式 自动属性 这个概念很简单,其简化了我们在.NET的时候手写一堆私有成员+属性的编程方式,我们只需要使用如下方式声明一个属性,编译器会自动生成所需的成员变量

Spark1.0.0新特性

Spark1.0.0 release于2014-05-30日正式公布,标志Spark正式进入1.X的时代.Spark1.0.0带来了各种新的特性,并提供了更好的API支持:Spark1.0.0添加了Spark SQL这一个新的重要组件,用于载入和操作Spark的结构化数据:Spark1.0.0增强了现有的标准库(ML,streaming,GraphX),同一时候还增强了Java和Python语言的支持:最后,Spark1.0.0在运维上做了非常大的改进,包含支持Hadoop/YARN安全机制.使