自定义View

自定义View(八) Path填充模式和最后的几个方法

2018-11-14  本文已影响0人  光羽隼

这算是Path最后一篇,主要看一下Path的两种填充模式。但是在这之前先把一下理解起来简单的列出来。

rXxx方法

rMoveTo(x,y);
 rLineTo(x,y);
 rQuadTo(controlX,controlY,endX,endY);
 rCubicTo(control1X,control1Y,control2X,controlY,endX,endY);

我们看到上边的方法都是在之前讲的一些方法前面加了r。
加了r的方法用的是相对位置,相对于上一个点的位置;
不加r的方法使用的是绝对位置,也就是使用的是坐标系的位置。

Path path = new Path();

path.moveTo(100,100);
path.lineTo(100,200);

canvas.drawPath(path,mDeafultPaint);
不加r
Path path = new Path();

path.moveTo(100,100);
path.rLineTo(100,200);

canvas.drawPath(path,mDeafultPaint);
加r
我们看到加了r的显示结果是第二个点的位置是相对于第一个位置的,而不是先对于坐标系的。第二个点的坐标应该是(100+100,100+200)r方法中的参数应该是上一个点的偏移量得到的点。

布尔操作

操作就是将两个path进行交集,并集,差集,异或得到新的path

// 对 path1 和 path2 执行布尔运算,运算方式由第二个参数指定,运算结果存入到path1中。
path1.op(path2, Path.Op.DIFFERENCE);

// 对 path1 和 path2 执行布尔运算,运算方式由第三个参数指定,运算结果存入到path3中。
path3.op(path1, path2, Path.Op.DIFFERENCE)
逻辑名称 类比 说明 示意图
DIFFERENCE 差集 Path1中减去Path2后剩下的部分 image
REVERSE_DIFFERENCE 差集 Path2中减去Path1后剩下的部分 image
INTERSECT 交集 Path1Path2相交的部分 image
UNION 并集 包含全部Path1Path2 image
XOR 异或 包含Path1Path2但不包括两者相交的部分 image

根据具体需求具体使用。

计算边界

void computeBounds (RectF bounds, boolean exact)

这个方法是用来测量一个path所占用的空间大小的,得到的结果存储在bounds中。后边一个exact已废弃,默认写true

// 移动canvas,mViewWidth与mViewHeight在 onSizeChanged 方法中获得
canvas.translate(mViewWidth/2,mViewHeight/2);

RectF rect1 = new RectF();              // 存放测量结果的矩形

Path path = new Path();                 // 创建Path并添加一些内容
path.lineTo(100,-50);
path.lineTo(100,50);
path.close();
path.addCircle(-100,0,100, Path.Direction.CW);

path.computeBounds(rect1,true);         // 测量Path

canvas.drawPath(path,mDeafultPaint);    // 绘制Path

mDeafultPaint.setStyle(Paint.Style.STROKE);
mDeafultPaint.setColor(Color.RED);
canvas.drawRect(rect1,mDeafultPaint);   // 绘制边界
path边界计算

重置路径

重置path的方法有resetrewind两种。
FillType填充规则

方法 是否保留FillType设置 是否保留原有数据结构
reset
rewind

选择权重: FillType > 数据结构

下面开始重头戏:填充模式

Path的填充模式

方法 判定条件 解释
奇偶规则 奇数表示在图形内,偶数表示在图形外 从任意位置p作一条射线, 若与该射线相交的图形边的数目为奇数,则p是图形内部点,否则是外部点。
非零环绕数规则 若环绕数为0表示在图形外,非零表示在图形内 首先使图形的边变为矢量。将环绕数初始化为零。再从任意位置p作一条射线。当从p点沿射线方向移动时,对在每个方向上穿过射线的边计数,每当图形的边从右到左穿过射线时,环绕数加1,从左到右时,环绕数减1。处理完图形的所有相关边之后,若环绕数为非零,则p为内部点,否则,p是外部点。

感觉讲了半天搞懂了,用起来也就那一句话。但还是建议去看安卓自定义View进阶-Path之完结篇里边关于两种规则的讲解。
我们通过这两种模式来判断是填充在图形外边还是图形里边。

Android 中的填充模式有四种:

模式 简介
EVEN_ODD 奇偶规则
INVERSE_EVEN_ODD 反奇偶规则
WINDING 非零环绕数规则
INVERSE_WINDING 反非零环绕数规则

Inverse 和含义是“相反,对立”,说明反奇偶规则刚好与奇偶规则相反,例如对于一个矩形而言,使用奇偶规则会填充矩形内部,而使用反奇偶规则会填充矩形外部,这个会在后面示例中代码展示两者对区别。

关于填充的几种方法

方法 作用
setFillType 设置填充规则
getFillType 获取当前填充规则
isInverseFillType 判断是否是反向(INVERSE)规则
toggleInverseFillType 切换填充规则(即原有规则与反向规则之间相互切换)

下边是奇偶和反奇偶规则的例子:

mDeafultPaint.setStyle(Paint.Style.FILL);                   // 设置画布模式为填充

canvas.translate(mViewWidth / 2, mViewHeight / 2);          // 移动画布(坐标系)

Path path = new Path();                                     // 创建Path

//path.setFillType(Path.FillType.EVEN_ODD);                   // 设置Path填充模式为 奇偶规则
path.setFillType(Path.FillType.INVERSE_EVEN_ODD);            // 反奇偶规则

path.addRect(-200,-200,200,200, Path.Direction.CW);         // 给Path中添加一个矩形
奇偶规则
反奇偶规则

使用非零环绕原则进行填充
前边提到的图形历经顺序会对填充有影响,印象就在这里:

mDeafultPaint.setStyle(Paint.Style.FILL);                   // 设置画笔模式为填充

canvas.translate(mViewWidth / 2, mViewHeight / 2);          // 移动画布(坐系)

Path path = new Path();                                     // 创建Path

// 添加小正方形 (通过这两行代码来控制小正方形边的方向,从而演示不同的效果)
// path.addRect(-200, -200, 200, 200, Path.Direction.CW);
path.addRect(-200, -200, 200, 200, Path.Direction.CCW);

// 添加大正方形
path.addRect(-400, -400, 400, 400, Path.Direction.CCW);

path.setFillType(Path.FillType.WINDING);                    // 设置Path填充模式为非零环绕规则

canvas.drawPath(path, mDeafultPaint);                       // 绘制Path
内部矩形顺时针
内部矩形逆时针
上一篇下一篇

猜你喜欢

热点阅读