安卓自定义View进阶 - Path之完结篇(伪)
来源:互联网 发布:沉默的螺旋 案例 知乎 编辑:程序博客网 时间:2024/06/05 08:43
Path之完结篇(伪)
作者微博: @GcsSloop
【本系列相关文章】
经历过前两篇 Path之基本操作 和 Path之贝塞尔曲线 的讲解,本篇终于进入Path的收尾篇,本篇结束后Path的大部分相关方法都已经讲解完了,但Path还有一些更有意思的玩法,应该会在后续的文章中出现吧,嗯,应该会的ˊ_>ˋ
一.Path常用方法表
为了兼容性(偷懒) 本表格中去除了在API21(即安卓版本5.0)以上才添加的方法。忍不住吐槽一下,为啥看起来有些顺手就能写的重载方法要等到API21才添加上啊。宝宝此刻内心也是崩溃的。
reset不保留内部数据结构,但会保留FillType.
rewind会保留内部的数据结构,但不保留FillType矩阵操作transform矩阵变换
二、Path方法详解
rXxx方法
此类方法可以看到和前面的一些方法看起来很像,只是在前面多了一个r,那么这个rXxx和前面的一些方法有什么区别呢?
rXxx方法的坐标使用的是相对位置(基于当前点的位移),而之前方法的坐标是绝对位置(基于当前坐标系的坐标)。
举个例子:
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
在这个例子中,先移动点到坐标(100,100)处,之后再连接 点(100,100) 到 (100,200) 之间点直线,非常简单,画出来就是一条竖直的线,那接下来看下一个例子:
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
这个例子中,将 lineTo 换成了 rLineTo 可以看到在屏幕上原本是竖直的线变成了倾斜的线。这是因为最终我们连接的是 (100,100) 和 (200, 300) 之间的线段。
在使用rLineTo之前,当前点的位置在 (100,100) , 使用了 rLineTo(100,200) 之后,下一个点的位置是在当前点的基础上加上偏移量得到的,即 (100+100, 100+200) 这个位置,故最终结果如上所示。
PS: 此处仅以 rLineTo 为例,只要理解 “绝对坐标” 和 “相对坐标” 的区别,其他方法类比即可。
填充模式
我们在之前的文章中了解到,Paint有三种样式,“描边” “填充” 以及 “描边加填充”,我们这里所了解到就是在Paint设置为后两种样式时不同的填充模式对图形渲染效果的影响。
我们要给一个图形内部填充颜色,首先需要分清哪一部分是外部,哪一部分是内部,机器不像我们人那么聪明,机器是如何判断内外呢?
机器判断图形内外,一般有以下两种方法:
PS:此处所有的图形均为封闭图形,不包括图形不封闭这种情况。
接下来我们先了解一下两种判断方法是如何工作的。
奇偶规则(Even-Odd Rule)
这一个比较简单,也容易理解,直接用一个简单示例来说明。
在上图中有一个四边形,我们选取了三个点来判断这些点是否在图形内部。
>
P1: 从P1发出一条射线,发现图形与该射线相交边数为0,偶数,故P1点在图形外部。
P2: 从P2发出一条射线,发现图形与该射线相交边数为1,奇数,故P2点在图形内部。
P3: 从P3发出一条射线,发现图形与该射线相交边数为2,偶数,故P3点在图形外部。
非零环绕数规则(Non-Zero Winding Number Rule)
非零环绕数规则相对来说比较难以理解一点。
我们在之前的文章 Path之基本操作 中我们了解到,在给Path中添加图形时需要指定图形的添加方式,是用顺时针还是逆时针,另外我们不论是使用lineTo,quadTo,cubicTo还是其他连接线的方法,都是从一个点连接到另一个点,换言之,Path中任何线段都是有方向性的,这也是使用非零环绕数规则的基础。
我们依旧用一个简单的例子来说明非零环绕数规则的用法:
PS: 注意图形中线段的方向性!
>
P1: 从P1点发出一条射线,沿射线防线移动,并没有与边相交点部分,环绕数为0,故P1在图形外边。
P2: 从P2点发出一条射线,沿射线方向移动,与图形点左侧边相交,该边从左到右穿过穿过射线,环绕数-1,最终环绕数为-1,故P2在图形内部。
P3: 从P3点发出一条射线,沿射线方向移动,在第一个交点处,底边从右到左穿过射线,环绕数+1,在第二个交点处,右侧边从左到右穿过射线,环绕数-1,最终环绕数为0,故P3在图形外部。
通常,这两种方法的判断结果是相同的,但也存在两种方法判断结果不同的情况,如下面这种情况:
注意图形线段的方向,就不详细解释了,用上面的方法进行判断即可。
自相交图形
自相交图形定义:多边形在平面内除顶点外还有其他公共点。
简单的提一下自相交图形,了解概念即可,下图就是一个简单的自相交图形:
Android中的填充模式
Android中的填充模式有四种,是封装在Path中的一个枚举。
我们可以看到上面有四种模式,分成两对,例如 “奇偶规则” 与 “反奇偶规则” 是一对,它们之间有什么关系呢?
Inverse 和含义是“相反,对立”,说明反奇偶规则刚好与奇偶规则相反,例如对于一个矩形而言,使用奇偶规则会填充矩形内部,而使用反奇偶规则会填充矩形外部,这个会在后面示例中代码展示两者对区别。
Android与填充模式相关的方法
这些都是Path中的方法。
示例演示:
本演示着重于帮助理解填充模式中的一些难点和易混淆的问题,对于一些比较简单的问题,读者可自行验证,本文中不会过多赘述。
奇偶规则与反奇偶规则
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
下面两张图片分别是在奇偶规则于反奇偶规则的情况下绘制的结果,可以看出其填充的区域刚好相反:
PS: 白色为背景色,黑色为填充色。
图形边的方向对非零奇偶环绕数规则填充结果的影响
我们之前讨论过给Path添加图形时顺时针与逆时针的作用,除了上次讲述的方便记录外,就是本文所涉及的另外一个重要作用了: “作为非零环绕数规则的判断依据。”
通过前面我们已经大致了解了在图形边的方向会如何影响到填充效果,我们这里验证一下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
布尔操作(API19)
布尔操作与我们中学所学的集合操作非常像,只要知道集合操作中等交集,并集,差集等操作,那么理解布尔操作也是很容易的。
布尔操作是两个Path之间的运算,主要作用是用一些简单的图形通过一些规则合成一些相对比较复杂,或难以直接得到的图形。
如太极中的阴阳鱼,如果用贝塞尔曲线制作的话,可能需要六段贝塞尔曲线才行,而在这里我们可以用四个Path通过布尔运算得到,而且会相对来说更容易理解一点。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
前面演示了布尔运算的作用,接下来我们了解一下布尔运算的核心:布尔逻辑。
Path的布尔运算有五种逻辑,如下:
布尔运算方法
通过前面到理论知识铺垫,相信大家对布尔运算已经有了基本的认识和理解,下面我们用代码演示一下布尔运算:
在Path中的布尔运算有两个方法
- 1
- 2
- 1
- 2
两个方法中的返回值用于判断布尔运算是否成功,它们使用方法如下:
``
Java
// 对 path1 和 path2 执行布尔运算,运算方式由第二个参数指定,运算结果存入到path1中。
path1.op(path2, Path.Op.DIFFERENCE);
// 对 path1 和 path2 执行布尔运算,运算方式由第三个参数指定,运算结果存入到path3中。path3.op(path1, path2, Path.Op.DIFFERENCE)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
计算边界
这个方法主要作用是计算Path所占用的空间以及所在位置,方法如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
它有两个参数:
关于exact如有疑问可参见Google官方的提交记录Path.computeBounds()
计算边界示例
计算path边界的一个简单示例.
代码:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
重置路径
重置Path有两个方法,分别是reset和rewind,两者区别主要有一下两点:
这个两个方法应该何时选择呢?
选择权重: FillType > 数据结构
因为“FillType”影响的是显示效果,而“数据结构”影响的是重建速度。
总结
Path中常用的方法到此已经结束,希望能够帮助大家加深对Path对理解运用,让大家能够用Path愉快的玩耍。( ̄▽ ̄)
(,,• ₃ •,,)
- 安卓自定义View进阶 - Path之完结篇(伪)
- 安卓自定义View进阶 - Path之完结篇(伪)
- 安卓自定义 View 进阶:Path 完结篇(伪)
- 安卓自定义View进阶-Path之完结篇
- 安卓自定义 View 进阶:Path 完结篇
- 安卓自定义View进阶-Path之基本操作
- 安卓自定义View进阶-Path之贝塞尔曲线
- 安卓自定义View进阶-Path之基本操作
- 安卓自定义View进阶-Path之贝塞尔曲线
- Android自定义View(十)_Path之完结篇(伪)
- 安卓自定义View进阶-Path基本操作
- 安卓自定义View进阶:Path基本操作
- 安卓自定义View进阶:Path基本操作
- 安卓自定义View进阶:Path基本操作
- 安卓自定义View进阶-Path之玩出花样(PathMeasure)
- 安卓自定义View进阶:Path之玩出花样(PathMeasure)
- 安卓进阶之自定义View
- 安卓自定义View进阶
- zynq-7000系列基于zynq-zed的vivado初步设计之linux下控制PL扩展的UART
- 最长回文子串-动态规划O(N^2)
- 第二章上机
- 关系型数据库与NOSQL
- PAT BASIC LEVEL 1052. 卖个萌 (20)
- 安卓自定义View进阶 - Path之完结篇(伪)
- Plugin with id 'com.neenbedankt.android-apt' not found.
- 453. Minimum Moves to Equal Array Elements | 计算步数
- div高度全屏
- Sqoop学习笔记 --- sqoop使用时候常见错误
- Heavy Transportation(最大生成树)
- 拼接字符串到url跳转页面后解析
- 4 Values whose Sum is 0 POJ - 2785(折半枚举)题解
- MeasureSpec学习 - 转