本文已授权微信公众号:鸿洋(hongyangAndroid)在微信公众号平台原创首发。

Android Support Library 23.2 出来以后,在Android 5.0(API级别21)以前的系统中,也可以定义矢量drawables,即VectorDrawable。它可以在不失清晰度的情况下进行缩放。你仅仅需要需要一个矢量图片的资源文件,而不再需要为每个屏幕密度设置一个资源文件,在一定程度上可以减小项目的体积。

vector 标签下的最主要就是 pathData,其实pathData跟Android中 Path api对路径的定义规则是差不多的,当你掌握了 pathData 的语法,同时有一颗不轻易放弃的心,就可以通过一些简洁的指令完成几乎所有的图案。

越是复杂的东西往往越有规律可循。下面就来详细说说pathData 的语法。给我五!

give me five.png

<!--上面的手掌对应的代码实现-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"android:width="24dp"android:height="24dp"android:viewportWidth="24"android:viewportHeight="24"><pathandroid:fillColor="#000000"android:pathData="M22,23 q0,4 -4,4 h-7 q-2,0 -3,-1 T1,16 q-0.6,-0.8 0,-2 t5,3q1,1 2,0 T8,4 q0,-1 0.9,-1.1 t1.1,1 1.5,9 q0.25,0.5 0.5,0.5t0.5,-0.5 0,-11 q0.2,-1 1.1,-1.1 t1.1,1.1 1,11 q0.25,0.5 0.5,0.5t0.5,-0.5 0.5,-9 q0.2,-1 1,-1 t1,1 0.5,9 q0.25,0.5 0.5,0.5t0.5,-0.5 1.2,-6.5 q0.3,-1 1,-1 t0.8,1 -0.8,6 T22,23"/>
</vector>

基本规则

pathData 的指令基本都是由字母跟若干数字组成,数字之间可以用空格或者逗号隔开 (其实逗号会被忽略掉,加上逗号只是一些习惯的问题)。一般来说指令字母分为大小写两种,大写的字母是基于原点的坐标系(偏移量),即绝对位置;小写字母是基于当前点坐标系(偏移量),即相对位置。

移动

  • M x,y (m dx, dy) 移动虚拟画笔到对应的点,但是并不绘制。一开始的时候默认是在(0,0)。

直线

  • L x,y (l dx, dy) 从当前点划一条直线到对应的点。
  • H x (h dx) 从当前点绘制水平线,相当于l x,0
  • V y (v dy) 从当前点绘制垂直线,相当于l 0,y
    <!--下面的例子除了 pathData, 其他跟此文件一样-->
    <vector xmlns:android="http://schemas.android.com/apk/res/android"android:width="24dp"android:height="24dp"android:viewportWidth="24"android:viewportHeight="24"><pathandroid:fillColor="#0000"android:strokeColor="#000"android:strokeWidth="0.2"android:pathData=" M10,10 L10,15 L15,15 L10,10"/>
    </vector>

直线

将上述代码 android:pathData=" M10,10 L10,15 L15,15 L10,10" 替换成以下代码效果相同

 android:pathData="M10,10 l 0,5 l 5,0 l-5,-5"  android:pathData="M10,10 V 15 H 15 L10,10"  android:pathData="M10,10 v 5 h 5 l-5,-5"

闭合

  • Z(或z) 从结束点绘制一条直线到开始点,闭合路径

上面的图形型也可以由以下代码绘制
android:pathData="M10,10 v 5 h 5 z"

弧线

  • A rx,ry x-axis-rotation large-arc-flag,sweepflag x,y
  • a rx,ry x-axis-rotation large-arc-flag,sweepflag dx,dy

    rx ry 椭圆半径
    x-axis-rotation x轴旋转角度
    large-arc-flag 为0时表示取小弧度,1时取大弧度(要长的还是短的)
    sweep-flag 0取逆时针方向,1取顺时针方向
    x,y (dx,dy) 终点的位置

这个弧线的指令比起直线就相对复杂得多了,7个参数容易搞混了。来看个例子
android:pathData="M8,10 a4,6 0 1,1 6 6"

弧线 (大弧,顺时针)

红色(8,10) 是起点, X轴旋转的角度为0,取大弧,顺时针,蓝色(14,16) 是终点。

  • 只将x-axis-rotation 改为30跟-30分别对应下面左边跟右边的效果,可见正数是按顺时针旋转负数按逆时针旋转。

    x-axis-rotation为30(左)、-30(右)

  • 只将large-arc-flag 改为 0 android:pathData="M8,10 a4,6 0 0,1 6 6" 对应下图效果

large-arc-flag为 0

  • 只将sweep-flag改为 0 android:pathData="M8,10 a4,6 0 1,0 6 6" 对应下图效果

sweep-flag为0

网上看到一张图,基本总结了弧线

二阶贝塞尔曲线

  • Q x1,y1 x,y ( q dx1,dy1 dx,dy)
  • T x,y ( t dx, dy)

先来看看二阶贝赛尔曲线的公式

没想到高数(高中数学)考过149分的我也研究不透这个鬼,还是看看动画吧

一下子感觉清晰了不少,对于Q指令来说(x1,y1)就是P1这个控制点,(x,y)就是终点P2。P0当然就是执行指令前最后的位置。这里有一点需要说明的, q dx1,dy1 dx,dy 这个指令,两个控制点都是相对P0点的。

而T指令又是什么鬼?为什么只有两个参数?其实T指令是在你画完一条贝塞尔曲线后,只需用T指令指定终点,就能画出一条平滑的贝塞尔曲线。控制点被默认为上一次的控制点关于上次终点的中心对称点。比如上次的控制点P1是(6,6),终点P2是(8,10), 那么使用T指令后默认控制点P1`为(10,14)。

举个例子:

 android:pathData="M4,10 Q6,6 8,10 Q10,14 12,10"  android:pathData="M4,10 Q6,6 8,10 T12,10" android:pathData="M4,10 q2,-4 4,0 q2,4 4,0"  android:pathData="M4,10  q2,-4 4,0 t4,0"

这四个对应的都是下面的曲线

二阶贝塞尔

三阶贝塞尔曲线

  • C x1,y1 x2,y2 x,y ( c dx1,dy1 dx2,dy2 dx,dy)
  • S x1,y1 x,y ( s dx1,dy1 dx, dy)

同样,先列下公式

这玩意估计也看不懂,还是结合动画来吧

跟二阶类似,但是三阶有两个控制点,分别是P1(x1,y1),P2(x2,y2)还有终点P3(x,y)。类似的, c dx1,dy1 dx2,dy2 dx,dy 所有的点都是相对于P0,即上一次的终点。

S指令跟T指令类似。S指令相对于C指令少了一个控制点,这个控制点就是上一次最后一个控制点相对上次的终点的中心对称点。还是同样举个例子:

 android:pathData="M4,10 C6,6 8,14 10,10 C12,6 14,14 16,10"android:pathData="M4,10 C6,6 8,14 10,10 S14,14 16,10"android:pathData="M4,10 c2,-4 4,4 6,0 c2,-4 4,4 6,0"android:pathData="M4,10 c2,-4 4,4 6,0 s4,4 6,0"

以上四个均会出现下图的效果

三阶贝塞尔

实践

终于把所有的指令搞清楚啦,那么接下来就来画一个比较简单的图案吧(为了一次性涉及几乎所有的指令,大家就别在意图画的很丑啦)

首先分析一下这个图的构成。它是一个圆角正方形同时里面有一个镂空的心型。先来看看正方形

<vector xmlns:android="http://schemas.android.com/apk/res/android"android:width="24dp"android:height="24dp"android:viewportWidth="40"android:viewportHeight="40"><pathandroid:fillColor="#f24e4e"android:pathData="M8,4h24 q4,0 4,4 v24 q0,4 -4,4h-24 q-4,0 -4,-4 v-24 q0,-4 4,-4"/>
</vector>

Paste_Image.png

细心的同学应该注意到这里没有设置strokeColor,strokeWidth,并且fillColor也不再设置透明了,所以出现的是没有边框的填充效果。上面viewportWidth为40,则把这张图分成40个单位。

在pathData中,首先移动到A(8,4),然后水平移动了24个单位到B(32,4)。接着就是一条二阶贝塞尔曲线,起点是B,控制点是C(36,4),终点是D(36,8)。然后再画一条垂直线到(36,32)…下面的操作都是差不多,就不多说的。这里注意一点,画这个正方形是从A-B-C-D,也就是顺时针的方向,这点对接下来画心型很重要。

画完了圆角正方形,接下来就要画一个镂空的心型。有同学说再加上一个path标签,设置不同颜色就可以。这方法乍一看挺不错,但是他实现的并不是镂空的效果,而是叠加的效果。镂空的话中间的心型是透明的,但是叠加就没办法让中间的心呈透明。

那怎么实现镂空的效果呢?其实关键就是前面说的方向。前面的正方形是顺时针的方向,如果我们在pathData 后面加上另一逆时针方向的路径,就会出现取反的效果,比如

    <pathandroid:fillColor="#f24e4e"android:pathData="M8,4h24 q4,0 4,4 v24 q0,4 -4,4h-24 q-4,0 -4,-4 v-24 q0,-4 4,-4M2,20 h20 v-10 z"/>

在刚才的基础上加上M2,20 h20 v-10 z ,这是一个逆时针方向的三角形,会变成下面这样

也就是说,我们只需要画一个逆时针方向的心型,就会出现上面的那个效果。先看看代码

    <pathandroid:fillColor="#f24e4e"android:pathData="M8,4h24 q4,0 4,4 v24 q0,4 -4,4h-24 q-4,0 -4,-4 v-24 q0,-4 4,-4M20,15a5,6 -15 0 0 -9,2c0,5 4,6 9,12c5,-6 9,-7 9,-12a5,6 15 0 0 -9 -2"/>

这个是在正方形的基础上加上

            M20,15a5,6 -15 0 0 -9,2c0,5 4,6 9,12c5,-6 9,-7 9,-12a5,6 15 0 0 -9 -2

我们看看如果pathData 单独设为上述路径会是什么样的

果然很漂亮。首先它从白色的点 (20,15)开始,向逆时针方向,也就是右边画了一段圆弧到蓝色的点(11,17),圆弧所在的椭圆逆时针转15°,取短弧,逆时针。然后再画一条三阶贝塞尔曲线,控制点分别是黄点(11,22),黑点(15,23),终点是绿色的点(20, 29)。这样子就完成了心型的一半了。另一半跟这边的完全对称,也就不细说了。

完整代码

<vector xmlns:android="http://schemas.android.com/apk/res/android"android:width="24dp"android:height="24dp"android:viewportWidth="40"android:viewportHeight="40"><pathandroid:fillColor="#f24e4e"android:pathData="M8,4h24 q4,0 4,4 v24 q0,4 -4,4h-24 q-4,0 -4,-4 v-24 q0,-4 4,-4M20,15a5,6 -15 0 0 -9,2c0,5 4,6 9,12c5,-6 9,-7 9,-12a5,6 15 0 0 -9 -2"/></vector>

一些废话

网上很多介绍VectorDrawable,但是介绍pathData的真的有点少。我也是通过查阅大量的资料,加上实践,基本算对pathData语法入门了吧,这东西掌握了真的不难,还可以装逼哈哈。这篇博客写的时间真的有点长,整整一天,第一写很多不懂的,希望大家多多指教。有机会再写一下Animated Vector Drawables。


感谢阅读到这里的你

Android vector 标签 pathData 详解相关推荐

  1. Android vector标签 PathData 画图超详解

    此文章来源于https://www.cnblogs.com/yuhanghzsd/p/5466846.html点击打开链接 Android vector标签 PathData 画图超详解 SVG是一种 ...

  2. android 按键用户点击事件,Android按键事件处理过程详解

    Android按键事件处理过程详解 (2013-09-26 14:05:19) 标签: it 在Android系统中,存在多种界面事件,如点击事件.触摸事件.焦点事件和菜单事件等,在这些界面事件发生时 ...

  3. Android的Logcat命令详解:翻译Enabling logcat Logging

    Android的Logcat命令详解 --翻译Enabling logcat Logging 田海立@CSDN 2011/07/28 Android LOG系统提供了收集和查看系统调试输出的功能.各种 ...

  4. Android WebView(一) WebView详解

    WebView,在Android开发中,我们总是会遇到,它是Google封装的,使用WebKit渲染引擎加载显示网页.接下来,我们就详细看看WebView的介绍以及使用.如果你想了解WebView主要 ...

  5. Android MIFARE读写器详解2

    Android MIFARE读写器详解2 Mifare是NXP公司生产的一系列遵守ISO14443A标准的射频卡,包Mifare S50.Mifare S70.Mifare UltraLight.Mi ...

  6. ANDROID L——Material Design详解(动画篇)

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! Android L: Google已经确认Android L就是Android Lolli ...

  7. Android NFC卡实例详解

    Android NFC卡实例详解 公司最近在做一个NFC卡片的工程,经过几天的时间,终于写了一个Demo出来,在此记录下在此过程中遇到的问题.由于之前本人是做iOS的,Android写起来并不是那么的 ...

  8. Android百度地图实例详解之仿摩拜单车APP(包括附近车辆、规划路径、行驶距离、行驶轨迹记录,导航等)

    Android百度地图实例详解之仿摩拜单车APP(包括附近车辆.规划路径.行驶距离.行驶轨迹记录,导航等) 标签: android百度地图行驶轨迹记录共享单车行驶距离和时间 2017-03-08 20 ...

  9. android zygote启动流程,Android zygote启动流程详解

    对zygote的理解 在Android系统中,zygote是一个native进程,是所有应用进程的父进程.而zygote则是Linux系统用户空间的第一个进程--init进程,通过fork的方式创建并 ...

最新文章

  1. 软件测试理论你知道多少?
  2. c#实现客户端程序自动下载更新(单独程序)
  3. dingo php,详细介绍Laravel+Dingo/Api 自定义响应
  4. 如何在Telegram机器人中设置推送通知
  5. 怎么用python自动梳理表格_Python将多份excel表格整理成一份表格
  6. [转]abstract 抽象类的概念和使用
  7. ucgui 字体生成与字体个性化编辑
  8. AI人工智能PyTorch深度学习
  9. 国土档案管理信息系统【档案查借阅登记】
  10. java求两数最小公倍数_java求解2个数的最小公倍数
  11. 标准差(standard deviation)
  12. 淘宝官方订单API接口,商品分类属性
  13. 关于AFNetworking上传图片问题
  14. Sablog-X v2.x 任意变量覆盖漏洞
  15. 学计算机专业1050显卡够不够,gtx1050显卡性能怎么样
  16. PS工作记录——图片元素复制,智能抠图
  17. python DEA: 基于非径向距离NDDF的Malmquist-Luenberger 指数及其分解
  18. JeeSite(JES)
  19. Linux无线网卡配置
  20. Mac版本的Sublime Text常用快捷键

热门文章

  1. iOS小技能:关闭Mac系统的SIP(System Integrity Protection 系统完整性保护)
  2. Kafka 在华泰证券的探索与实践
  3. U盘显示1字节怎么办?
  4. maya找回丢失的材质
  5. javaScript获取当前时间方法
  6. 2020年苏州大学872真题整理【回忆版】
  7. python语言编程入门第一讲-第1讲:Python基本知识快速入门
  8. 荣耀智慧屏X1鸿蒙,荣耀智慧屏X1体验:1699元的55寸4K大屏+鸿蒙OS体验如何?
  9. sql删除主键并添加主键
  10. C#获取Excel表格所有sheet名(Epplus)