Android矢量图动画:每人送一辆掘金牌小黄车

看完本文,每人送一台小黄车,掘金牌的~html

不得不说,矢量图在项目中用得少之又少,却很香!可缩放矢量图形(SVG)是一套语法规范,常在前端中使用,而VectorDrawable(Android中的矢量图)只实现了SVG的部分语法。使用VectorDrawable代替位图能够减少 APK 的大小,由于能够针对不一样的屏幕密度调整同一文件的大小,而不会下降图片质量,同时能够实现一些复制的效果图。前端

能够从下面两个地方得到经常使用矢量图:android

  • IconFont
  • Android Stuido 自带的 Vector Asset Studio工具

Android版本兼容问题web

因为兼容低版本问题,致使矢量图得不到推广吧?可是如今大多数手机系统都Android 5.0起步了吧。app

矢量图VectorDrawable仅支持到Android 4.4,经过支持库可最低支持到Android 2.1。编辑器

矢量图动画AnimatedVectorDrawable仅支持到Android 5.0,经过支持库最低支持到Android 3.0。 Gralde配置工具

android {
 defaultConfig {  vectorDrawables.useSupportLibrary = true  }  }   dependencies {  //须要 Android 支持库 23.2 或更高版本以及 Android Plugin for Gradle 2.0 或更高版本  implementation 'com.android.support:appcompat-v7:23.2.0'  } 复制代码

美图减压鉴赏: 布局

矢量图

经过Android Studio的Vector Asset Studio工具来获取一张矢量图。post

根据我的喜爱配置Vector Assert。 会在drawable文件夹生成资源文件,例如这里生成ic_menu.xml文件:flex

<vector xmlns:android="http://schemas.android.com/apk/res/android"
 android:width="24dp"  android:height="24dp"  android:viewportWidth="24"  android:viewportHeight="24"  android:tint="?attr/colorControlNormal">  <path  android:fillColor="@android:color/white"  android:pathData="M3,18h18v-2L3,16v2zM3,13h18v-2L3,11v2zM3,6v2h18L21,6L3,6z"/> </vector> 复制代码

没了解过矢量图,相信是看不懂path标签pathData属性的内容。

vector标签设置矢量图大小,widthheight属性分别为24dpviewportWidthviewportHeight属性表示画布的大小,表示将矢量图等分的份数,这里划分为24*24。能够理解在一张24dp*24dp的图片上有24*24个小方格,经过这些小方格,能够绘制不一样图案。

path能够理解为路径,图片绘制的内容。fillColor属性表示填充颜色,pathData属性表示在图片上做画内容。

pathData属性的值是SVG的语法内容,经过下面的内容就能够了解pathData属性值的含义了。

经常使用命令:

  • M x,y 移动到坐标(x,y)。M3,18表示将画笔移动到坐标(3,18)

  • L x,y从当前的位置画一条直线到指定的位置(x,y)。

  • H x 画水平线到x位置。

  • V y 画垂直线到y位置。

  • Z 闭合,链接终点和起点

  • A rx,ry,xRotationAnagle,radianFlag,sweepFlag,x,y 画弧线,理解为椭圆的一部分,rxry表示 x轴和y轴半径,即椭圆的长短轴问题;xRotationAnagle表示x轴旋转角度(搞不明白用法);radianFlag 0表示取小弧度,1表示取大弧度;sweepFlag 0表示逆时针,表示1顺时针画弧线;xy弧线的终点位置,起点位置为画笔所在的地方。

  • C x1,y1,x2,y2,x3,y3 三次贝赛曲线

  • S x2,y2,x,y 光滑三次贝塞尔曲线

  • Q x1,y1,x2,y2 二次贝赛曲线

  • T x,y 映射

ps:大写表示绝对坐标,小写表示相对坐标。

pathData标签内容进行解读:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
 android:width="24dp"  android:height="24dp"  android:viewportWidth="24"  android:viewportHeight="24"  android:tint="?attr/colorControlNormal">  <path  android:fillColor="@android:color/white"  android:pathData="M3,18 h18 v-2 L3,16 v2 z M3,13 h18 v-2 L3,11 v2 z M3,6 v2 h18 L21,6 L3,6 z"/> </vector> 复制代码

M3,18 将画笔移动到坐标(3,18);

h18从坐标(3,18)到坐标(21,18)画一条水平直线;

v-2从坐标(21,18)到坐标(21,16)画一条垂直直线;

L3,16从坐标(21,18)到坐标(3,16)画一条直线;

v2从坐标(3,16)到坐标(3,18)画一条垂直直线;

z 闭合起点和终点。

到这里,最底部的直线就会画出来了,其余两条线是相同原理。

注意事项:不要将pathData的值抽离出来放到string.xml文件,否则在兼容5.0如下机型生成png图片,会报pathData错误。

path标签除了pathData属性,还有哪些可用的属性呢?

path标签

path标签可用属性:

  • name:路径名称,可在其余地方引用,例如矢量图动画引用;
  • strokeWidth:线条宽度,单位为 viewportHeightviewportWidth中的1等分;。
  • strokeColor:线条颜色;
  • strokeAlpha:线条透明度。 0f->1f
  • strokeLineJoin:线条拐角的形状。圆角 round、斜切尖角 miter、斜角 bevel,例如正方形的四个角;
  • strokeLineCap:线条线帽形状。圆角 round、正方形 square、臂 butt
  • strokeMiterLimit:斜线miter与strokeWidth的比例上限。若是比例值超过这个值,再也不显示尖角而是bevel斜角。当 strokeLineJoin属性设置为 miter才生效。
  • fillColor:填充颜色;
  • fillType:填充类型,取值 nonZeroevenOdd;
  • fillAlpha:填充透明度;
  • trimPathStart:从路径开始位置剪掉比率的内容,留下剩下的, 0f->1f;
  • trimPathEnd:从路径开始位置截取比率的内容,留下截取的内容, 0f->1f;
  • trimPathOffsettrimPathStarttrimPathEnd的偏移量 0f->1f;

例如:

XML布局以下:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
 android:width="24dp"  android:height="24dp"  android:viewportWidth="24"  android:viewportHeight="24">  <path  android:name="triangle"  android:pathData="M3,18 h18 v-5 L3,13 v5 z "  android:strokeWidth="1"  android:strokeLineJoin="round"  android:strokeAlpha="0.9"  android:strokeColor="@color/white"  android:trimPathStart="0.1"  android:strokeLineCap="round"  android:trimPathOffset="0.15"  /> </vector> 复制代码

PreView效果以下:

group标签

group标签主要是将多个path标签组合起来,子标签也能够是group标签,其属性做用于全部子标签,有如下属性:

  • name: 定义 group标签名称;
  • translateX: x轴位移;
  • translateY: y轴位移;
  • rotation: 旋转;
  • scaleX: x轴缩放;
  • scaleY: y轴缩放;
  • pivotX: 缩放与旋转参考点X;
  • pivotY: 缩放与旋转参考点y; 栗子:

XML布局代码:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
 android:width="24dp"  android:height="24dp"  android:viewportWidth="24"  android:viewportHeight="24">   <group  android:name="triangleGroup"  android:rotation="10"  android:translateX="1"  android:translateY="1"  android:scaleX="0.5f"  android:scaleY="0.5f"  android:pivotX="0.5"  android:pivotY="0.5">  <path  android:fillColor="@color/colorPrimary"  android:pathData="M6,6 L9,12 H3 z"  android:strokeWidth="0.5"  android:strokeColor="@color/white"  android:strokeLineJoin="round" />   <path  android:fillColor="@color/chart_color_1"  android:pathData="M18,6 L21,12 H15 z"  android:strokeWidth="0.5"  android:strokeColor="@color/white"  android:strokeLineJoin="bevel" />   </group> </vector> 复制代码

效果图:

矢量图动画

只要胆子大,没有实现不了的矢量图,加上点动画效果那就更炫酷吊了。属性动画了解多少呢?好文连接==>:Android属性动画,看完这篇够用了吧

矢量图动画步骤

  1. 实现矢量图
  2. 实现属性动画
  3. 实现矢量属性动画粘合剂
  4. 布局引用,代码开始动画

轨迹动画

轨迹动画主要利用属性动画设置矢量图的trimPathStarttrimPahtEnd属性。要正确实现轨迹动画的前提条件:矢量图是一笔画出的,不能存在屡次挪画笔的操做。

示例:

  1. 在drawable文件夹下建立 vector_text.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"  android:width="240dp"  android:height="240dp"  android:viewportWidth="24"  android:viewportHeight="24">   <path  android:name="pathText"  android:pathData="M9,6 L12,12 L15,6.5 18,12 21,6"  android:strokeWidth="0.5"  android:strokeColor="@color/white"  android:strokeLineCap="round"  android:strokeLineJoin="round" /> </vector> 复制代码

画了一个白色的W:

2. 在animator文件夹下建立animator_text.xml文件。定义一个属性动画,操做矢量图的trimPathEnd属性。

<?xml version="1.0" encoding="utf-8"?>
<set  xmlns:android="http://schemas.android.com/apk/res/android">   <objectAnimator  android:duration="2000"  android:propertyName="trimPathEnd"  android:valueFrom="0"  android:valueTo="1"  android:repeatMode="reverse"  android:repeatCount="infinite"  android:valueType="floatType" />  //这里顺便操做矢量图的画笔颜色  <objectAnimator  android:duration="2000"  android:propertyName="strokeColor"  android:valueFrom="@color/white"  android:repeatMode="reverse"  android:repeatCount="infinite"  android:valueTo="@android:color/holo_blue_dark"  android:valueType="colorType" />  </set> 复制代码
  1. drawable文件夹下建立 animator_vector_text.xml文件,组合矢量图和属性动画,成为它两的粘合剂。因为兼容问题,须要在 drawable-v21文件夹下建立。
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
 android:drawable="@drawable/vector_text">  <target  android:name="pathText"  android:animation="@animator/animator_text" /> </animated-vector> 复制代码

animated-vector标签的drawable属性值是第一步定义的矢量图文件名。target标签的name属性是咱们在矢量图中定义的;而animation属性则是第二部定义的属性动画文件名。

  1. 在布局在引用 animator_vector_text文件
<ImageView
 android:id="@+id/iv"  app:srcCompat="@drawable/vector_animator_text"  android:layout_width="match_parent"  android:layout_height="wrap_content" /> 复制代码
  1. 在代码中开始动画:
val animatable = iv.drawable as Animatable
 animatable.start() 复制代码

效果图:

路径动画

路径动画是利用矢量图中相同的关键点进行变幻的过程。

Android 5.0前不支持路径动画。

示例:

  1. 在drawable文件夹下建立 vector_line.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"  android:width="240dp"  android:height="240dp"  android:viewportWidth="24"  android:viewportHeight="24">   <path  android:name="pathLine"  android:pathData="M9,6 L12,6 L15,6 18,6 21,6"  android:strokeWidth="0.5"  android:strokeColor="@color/white"  android:strokeLineCap="round"  android:strokeLineJoin="round" /> </vector> 复制代码

咱们定义了几个关键点,画了一条直线:

2. 在animator文件夹下建立animator_morphing.xml文件。定义一个属性动画,操做矢量图的pathData属性。valueFrom是第一步建立直线矢量图的属性pathData的值,valueToW矢量图的pathData的值。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">  <objectAnimator  android:duration="2000"  android:propertyName="pathData"  android:valueFrom="M9,6 L12,6 L15,6 18,6 21,6"  android:valueTo="M9,6 L12,12 L15,6.5 18,12 21,6"  android:valueType="pathType" /> </set> 复制代码
  1. drawable文件夹下建立 animator_vector_line.xml文件,组合矢量图和属性动画,成为它两的粘合剂。因为兼容问题,须要在 drawable-v21文件夹下建立。
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"  android:drawable="@drawable/vector_line">  <target  android:name="pathLine"  android:animation="@animator/animator_morphing" /> </animated-vector> 复制代码
  1. 在布局在引用 animator_vector_text文件
<ImageView
 android:id="@+id/iv"  app:srcCompat="@drawable/vector_animator_line"  android:layout_width="match_parent"  android:layout_height="wrap_content" /> 复制代码
  1. 在代码中开始动画效果:
val animatable = iv.drawable as Animatable
 animatable.start() 复制代码

效果图

到这里就结束了,下面是属于你们的小黄车~

你们的小黄车

实例demo演示,用了2小时给你们制做的小黄车,但愿不要嫌弃:

  1. 在drawable文件夹下建立vertor_bicycle.xml文件夹,内容以下:
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"  android:width="300dp"  android:height="300dp"  android:viewportWidth="200"  android:viewportHeight="200">   <!--左车轮-->  <group  android:name="leftWheel"  android:pivotX="40"  android:pivotY="70">   <path  android:name="leftWheelAxle"  android:pathData="M 40,70 L23,80M 40,70 L40,50 M 40,70 L57,80"  android:strokeWidth="1"  android:strokeColor="@color/white" />    <path  android:pathData="M 60,70 A 20,20,0,1,1,60,69 z"  android:strokeWidth="1"  android:strokeColor="@color/white" />   </group>  <!--右车轮-->  <group  android:name="rightWheel"  android:pivotX="130"  android:pivotY="70">   <path  android:name="rightWheelAxle"  android:pathData="M 130,70 L113,80 M 130,70 L130,50 M 130,70 L147,80"  android:strokeWidth="1"  android:strokeColor="@color/white" />   <path  android:pathData="M 150,70 A 20,20,0,1,1,150,69 z"  android:strokeWidth="1"  android:strokeColor="@color/white" />  </group>  <!--车链盒子-->  <path  android:name="chainBox"  android:fillColor="@color/colorPrimary"  android:pathData="M 35,62 h54 v12 H35 z"  android:strokeWidth="1"  android:strokeColor="@color/white" />  <!--车架-->  <path  android:pathData="M 50,69 L 65,40 L 80,69 M 86,65 L110,31  v 20 L130,70 "  android:strokeWidth="2"  android:strokeColor="@color/colorPrimary"  android:strokeLineJoin="round" />  <!--前车轮挡板-->  <path  android:pathData="M105,73 A 20,20,0,1,1,125,85"  android:strokeWidth="2"  android:strokeColor="@color/colorPrimary"  android:strokeLineJoin="round"  android:trimPathEnd="0.4" />  <!--车把-->  <path  android:pathData="M 110,31 V20 l -10,-4 h -3 M110,21 l -4,-10 h-3"  android:strokeWidth="2"  android:strokeColor="@color/white"  android:strokeLineCap="round"  android:strokeLineJoin="round" />  <!--车篮-->  <path  android:fillColor="@color/white"  android:pathData="M 111,41 h 21 v -12 H 111 z"  android:strokeWidth="1"  android:strokeColor="@color/white"  android:strokeLineCap="square"  android:strokeLineJoin="round" />  <!--掘金LOGO-->  <path  android:fillColor="@color/colorPrimary"  android:pathData="M 121,30 L122,31 L121,32 L120,31 z"  android:strokeWidth="0.5"  android:strokeColor="@color/colorPrimary"  android:strokeLineCap="square"  android:strokeLineJoin="miter" />  <path  android:pathData=" M119,33 L121,35,L123,33  M118,34 L121,37,L124,34"  android:strokeWidth="0.5"  android:strokeColor="@color/colorPrimary"  android:strokeLineCap="square"  android:strokeLineJoin="miter" />  <!--皮座-->  <path  android:fillColor="@color/white"  android:pathData="M 55,40 h 20 v-4 H56 v-3h-2"  android:strokeWidth="1"  android:strokeColor="@color/white"  android:strokeLineCap="square"  android:strokeLineJoin="round" />  <!--脚踏板-->  <group  android:name="pedal"  android:pivotX="82"  android:pivotY="68">  <path  android:pathData="M 82,68 L 98,80"  android:strokeWidth="0.5"  android:strokeColor="@color/white"  android:strokeLineCap="round" />   <path  android:fillColor="@color/white"  android:pathData="M 96,80 A 2,2,0,1,1,96,81 z"  android:strokeWidth="1"  android:strokeColor="@color/white" />  </group> </vector> 复制代码

预览图:

2. 在animator文件夹下建立animator_wheel.xml文件,实现车轮和脚踏旋转属性动画:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">  <objectAnimator  android:interpolator="@android:interpolator/linear"  android:propertyName="rotation"  android:repeatCount="infinite"  android:valueType="floatType"  android:valueFrom="0f"  android:valueTo="360f"  android:repeatMode="restart"  android:duration="2000"/>  //能够再增长其余动画效果,例如颜色变化 </set> 复制代码
  1. animator文件夹下建立 animator_bicycle_left_to_right.xml布局文件,实现单车从左到右移动属性动画:
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
 android:propertyName="translationX"  android:valueFrom="-600f"  android:valueTo="900f"  android:valueType="floatType"  android:repeatCount="infinite"  android:repeatMode="restart"  android:duration="9000"  android:interpolator="@android:interpolator/linear"  /> 复制代码
  1. drawable文件夹下建立 verctor_animator_bicycle.xml文件,实现单车矢量图和属性动画的粘合剂,也就是最终的矢量图动画。因为兼容问题,须要在drawable-v21文件夹下建立。
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"  android:drawable="@drawable/vertor_bicycle">   <target  android:animation="@animator/animator_wheel"  android:name="leftWheel"/>   <target  android:animation="@animator/animator_wheel"  android:name="rightWheel"/>   <target  android:animation="@animator/animator_wheel"  android:name="pedal"/> </animated-vector> 复制代码
  1. 在布局中引用 verctor_animator_bicycle.xml文件,
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent"  xmlns:app="http://schemas.android.com/apk/res-auto"  android:background="@color/black">   <ImageView  android:id="@+id/iv"  app:srcCompat="@drawable/verctor_animator_bicycle"  android:layout_width="match_parent"  android:layout_height="wrap_content" />   <TextView  android:id="@+id/btnStart"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:layout_alignParentBottom="true"  android:layout_centerHorizontal="true"  android:layout_marginBottom="50dp"  android:background="@color/white"  android:padding="10dp"  android:text="开始"  android:textColor="@color/colorPrimary"  android:textSize="16sp" /> </RelativeLayout> 复制代码
  1. AppCompatActivity中代码调用:
btnStart.setOnClickListener {
 val animatable = iv.drawable as Animatable  animatable.start()  } 复制代码

此时效果图: 7. 加上从左到右的属性动画:

btnStart.setOnClickListener {
 val animatable = iv.drawable as Animatable  animatable.start()   val animator = AnimatorInflater.loadAnimator(this, R.animator.animator_bicycle_left_to_right)  animator.setTarget(iv)  animator.start()  } 复制代码

效果图:

好了哇,你们的小黄车已经造好,请给文章点个赞领取,若是不满意,能够自行定制小黄车哦~

要啥自行车,想要个赞而已

参考文章:

Android属性动画,看完这篇够用了吧

官网

Android 5.0+ 高级动画开发系列 矢量图动画

Android Vector曲折的兼容之路

本文使用 mdnice 排版

相关文章
相关标签/搜索