❶ 安卓开发中矢量图的绘制及动画
矢量图也称为面向对象的图像或绘图图像,是根据几何特性来绘制的图形,在安卓开发中可以使用失量图代替原来的图片资源,矢量图具有占用空间小和可以随意缩放但不失真的优势,在我的多个项目中都有运用。
通过学习和实践,我总结了一些与矢量图相关的知识,方便今后更好的使用矢量图,同时也可以供大家查阅参考。
绘制矢量图之前需要先定义画布的宽高,后续的绘制效果都展示在这个画布上。在绘制过程中需要输入的坐标就是这个画布上的点。
安卓的矢量图常见于 drawable 文件夹下,是一个xml文件,由 vector 标签包裹,在 vector 标签中可包含多个 path 标签,依次叠加显示。
在矢量图中最重要的就是 path 属性,图像的样式就是由 path 属性中的数据绘制而成,这些数据由不同的命令组合而成,下面就介绍一些矢量图的绘制命令。
将前面的命令示例连接起来就可以生成一个完整的图像,它大概长这个样子:
画布的尺寸为500x500,图上的顶点是200,10的位置,也是我们开始作图的起点。通过这个图片可以更好的理解每一个绘图命令。
安卓中可以为矢量图添加动画效果,这样用户就可以看到一个动的图片,可以一定程度的提高app的交互效果。矢量图动画是图形内部的变化,可以做到View动画无法实现的效果。
这种动画针对的是矢量图中 path 字段的值,通过连续改变 path 字段的值而达到产生动画的效果。
注:pathData动画所需的AnimatedVectorDrawable最低要求API等级为25
实现一个矢量图动画需要以下几步:
1. 准备起始状态和结束状态的矢量图两张。
2. 创建动画配置文件。
3. 创建动画矢量图文件。
4. 启动动画。
基于这种要求,我准备了两个矢量图:
控制动画运行的是一个 objectAnimator ,此处把 objectAnimator 包裹在一个 set 中也是可以的,说白了就是执行这个动画文件。
ration 用来指定动画的持续时间。
propertyName 中的pathData指的就是矢量图中的pathData。
valueFrom 和 valueTo 一个是起始路径,一个是结束路径,可以想到,这个动画就是在持续修改pathData,从而达到展示动画的效果。而 valueFrom 和 valueTo 的值是直接从先前准备的矢量图中复制过来的,所以那个结束状态的矢量图中唯一有用的东西就是pathData属性,没有那个文件也无所谓。
valueType 这里必须填判型写pathType,这是专门用来计算path的类型。
此时,文件的最外层由 animated-vector 包裹,同时需要添加一个 drawable 参数,这个 drawable 用于指定动画应用于那个矢量图上,我们是要从未启用状态变成启用状态,所以是在未启用状态开始执行动画,在动画未开始的时候展示的也是未启用状态。此处我们指定为 @drawable/icon_filter_off 。
内部有一个 target 标签,这个标签可以有多个,分别对应不同的动画,但同一个 path 只能应用一个动画。
name 用于指定要执行动画的 path 。status正是我们为右下角小图标path设置的名称。
animation 用于指定需要执行的动画。此处引用我们刚刚创建的猛冲山动画资源 @animator/filter_turn_on 。
当我们创建枝中好动画矢量图之后,页面中引用的资源就不再是之前的静态矢量图了,需要把 ImageView 的图片替换成 @drawable/animated_filter_on
经过这么多的步骤,我们终于做出了一个矢量图动画,而且是一个。说实话,有点累,然而我这个状态切换的动画一套就要两个,所以我又加了一个回来的动画和对应的动画矢量图,一共六个文件,完成了筛选状态的两个切换动画。这还是比较简单的实现方式,对于两种状态切换的动画,网上还有一种使用selector的方式,这种方式更麻烦,而且使用方法并没有简单一些,所以我的选择是在需要切换状态的时候更改 ImageView 的图片资源,然后再执行动画。
trimPath动画相当于是改变了矢量图绘制的位置,是从头开始画还是从80%的位置开始画,然后再动态的修改这个百分比,从而达到动画的效果。理解起来倒不是很难。
先放一个我使用trimPath动画做的loading效果,这个动画效果被我用在LoadingDialog中,在界面加载的时候会重复播放这个动画。
android:name="load" 不用多说,这个是我们做动画时路径名称。这里为了让心电图路径更清晰,我设置了描边宽度为20( android:strokeWidth="20" ),同时还要设置描边的颜色才能展示出来。后面的 android:trimPathStart="0" 和 android:trimPathEnd="0" 是本次trimPath动画的重点。
这两个属性都设置为0是因为动画的起始帧都为0,然后通过 objectAnimator 慢慢把这两个属性变为1,这样一个慢慢增长的动画就形成了。
网络上一个横线变成搜索按钮的示例是将这两个属性分别应用到了两个 path 上,而我是将两个属性同时应用到一个 path 上,原理都是一样的。
在配置文件中,我将两个动画都设置为3秒且循环播放,起始点的动画慢于终点的动画1秒,达到只画中间1秒间隔线段的效果。和路径变形动画的区别是 android:valueType="floatType" ,我们只需要计算从0到1的数字,然后应用到 trimPathStart 和 trimPathEnd 字段上。至此,loading的动画就配置完了。
这一步已经没什么可说的了,就是将指定的矢量图中指定的路径设置一个指定的动画。
通过几天的学习,已经大致掌握了矢量图的展示及动画的制作,但这一套流程下来成本比较高,是程序员方式的动画制作流程。除了制作成本,创意成本也是相当高的,一个好的创意能极大的提升用户体验,而好多时候我们的创意能够被实现也是很困难的。希望以后能实现一些更好的效果,让用户使用起来更舒服。
SVG—最简单的SVG动画
SVG路径(path)中的圆弧(A)指令的语法说明及计算逻辑
Android中的矢量图
Android高级动画(2)
❷ 如何使用Android的VectorDrawable类绘制矢量图
绘制矢量图形非难事——如何使用Android的VectorDrawable类
内容概述
尽管Android系统并不能够直接支持SVG(即可缩放矢量图形),但Lollipop版本却引入了一个名为VectorDrawable的新类,其允许设计人员及开发人员以纯代码方式生成类似的绘制效果。
在今天的文章中,我们将共同学习如何利用XML文件创建一个VectorDrawable,并将其以动画方式显示在自己的项目当中。这项功能只能在运行有Android 5.0或者更高版本的设备上实现,而且目前还不具备任何支持库实现。本篇教程中的相关源文件可以通过GitHub网站获取。
1. 创建Vector Drawable
从相似角度来看,VectorDrawable与标准SVG图形都是利用path值绘制完成的。不过如何利用SVG path绘制图形并不在本篇文章的探讨范围之内,大家可以点击此处从W3C网站处获取必要的说明资料。在本文当中,我们只需要了解到path标签的作用是进行图形绘制即可。让我们首先从SVG文件入手,看看以下图形是如何被绘制出来的:
这一图形共由五个主要部分所组成:
一个圆角四边形作为CPU主体,该四边形由两条拱状弧线构成。
四组各自包含五根线条的图形,用于充当CPU的外延线路。
以下代码所示为如何以SVG方式绘制以上图形:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve"> <path id="cpu" d=" M341.087,157.478c7.417,0,13.435,6.018,13.435,13.435v170.174 c0,7.417-6.018,13.435-13.435,13.435H170.913 c-7.417,0-13.435-6.018-13.435-13.435V170.913 c0-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 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 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 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 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" /> </svg>
虽然看起来有点繁杂,但大家其实用不着纠结于以上代码的具体含义,而且这完全不会影响到我们接下来要进行的VectorDrawable绘制工作。不过需要强调的是,我将前面提到的五大图形组成部分在代码中作为独立的区块来处理,这是为了增强代码内容的可读性。
首先,我们需要利用两条拱形弧线来绘制出圆角四边形,而在接下来的内容中我们会探讨如何分别表现出上、下、左、右四个方位的外延线条。为了将上述SVG代码转化为VectorDrawable,大家首先需要在XML当中定义vector对象。以下代码提取自本篇文章示例代码当中的vector_drawable_cpu.xml文件。
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="64dp" android:width="64dp" android:viewportHeight="600" android:viewportWidth="600" > </vector>
在此之后,大家可以向其中添加path数据。下列代码同样被拆分成了五个不同的path标签而非将其作为整体处理,这当然也是为了保证内容的可读性。
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="64dp" android:width="64dp" android:viewportHeight="600" android:viewportWidth="600" > <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" /> <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" /> <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" /> <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" /> <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" /> </vector>
正如大家所见,每个path片段都只需要利用pathData属性进行绘制。现在我们可以将VectorDrawable XML文件作为一个可绘制对象纳入到标准ImageView当中,而且其能够根据应用程序的实际需要任意进行尺寸缩放——完全不需要再修改任何Java代码。
2. 为Vector Drawables添加动画效果
现在我们已经了解了如何以纯代码方式创建图形,接下来要做的是找点乐子——为其添加动画效果。在以下动画中,大家会发现作为延伸线路的各组线条会不断指向并远离CPU本体进行移动。
为了达到这一目标,大家需要将包含动画效果的每个片段包含在一个<group>标签当中。经过修改的vector_drawable_cpu.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="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>
接下来,我们需要为每个动画类型创建animator文件。在本次示例中,每组线路各使用一个animator,这就意味着共需要四个animator。以下代码所示为上方线路的动画效果,大家还需要为下、左、右线路设定类似的效果。每个animator XML文件都被包含在了本项目的示例代码当中。
<?xml version="1.0" encoding="utf-8"?> <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:ration="250" /> </set>
如大家所见,propertyName被设定为translateY,这意味着该动画将沿Y轴方向移动。而valueFrom与valueTo则控制着位移的起点与终点。通过将repeatMode设置为reverse而repeatCount设置为infinite,整个动画会一直循环下去,其效果则在VectorDrawable处体现出来。该动画的ration被设定为250,其时长单位为毫秒。
为了将该动画应用到自己的可绘制文件当中,大家需要创建一个新的animated-vector XML文件,从而将这些animator分配给各VectorDrawable组。以下代码的作用是创建该animated_cpu.xml文件。
<?xml version="1.0" encoding="utf-8"?> <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/vector_drawable_cpu"> <target
http://mobile.51cto.com/news-478709.htm