Android自定义视图 View 之重要知识点 Path 详解

Posted 黄毛火烧雪下

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android自定义视图 View 之重要知识点 Path 详解相关的知识,希望对你有一定的参考价值。

惯例:先上图后说话,谢谢各位伙伴的支持! 有你们是我的福分!

             欢迎一起讨论和学习,QQ:732258496  微信:15520726587


 每日一言:梦想一定要有万一实现了呢!

Path常用方法

方法作用备注
moveTo移动起点移动下一次操作的起点位置
lineTo连接直线连接上一个点到当前点之间的直线
setLastPoint设置终点重置最后一个点的位置
close闭合路劲从最后一个点连接最初的一个点,形成一个闭合区域
addRect添加矩形添加矩形到当前Path
addRoundRect添加圆角矩形添加圆角矩形到当前Path
addOval添加椭圆添加椭圆到当前Path
addCircle添加圆添加圆到当前Path
addPah添加路劲添加路劲到当前Path
addArc添加圆弧添加圆弧到当前Path
arcTo圆弧绘制圆弧,注意和addArc的区别
isEmpty是否为空判定Path是否为空
isRect是否为矩形判定Path是否是一个矩形
set替换路劲用新的路劲替换当前路劲的所有内容
offset偏移路劲对当前的路劲进行偏移
quadTo贝塞尔曲线二次贝塞尔曲线的方法
cubicTo贝塞尔曲线三次贝塞尔曲线的方法
rMoveTo,rlineTo,rQuadTo,rCubicTorXxx方法不带r的方法是基于原点坐标系(偏移量),带r的基于当前点坐标系(偏移量)
op布尔操作对两个Path进行布尔运算(交集,并集)等操作
setFillType填充模式设置Path的填充模式
getFillType填充模式获取Path的填充
isInverseFillType是否逆填充判断是否是逆填充模式
toggleInverseFillType相反模式切换相反的填充模式
getFillType填充模式获取Path的填充
incReserve提示方法提示Path还有多少个点等待加入
computeBounds计算边界计算Path的路劲
reset,rewind重置路劲清除Path中的内容(reset相当于new Path , rewind 会保留Path的数据结构)
transform矩阵操作矩阵变换

Path方法使用详解

使用Path不仅可以绘制简单的图形(如圆形,矩形,直线等),也可以绘制复杂一些的图形(如正多边形,五角星等),还有绘制裁剪和绘制文本都会用到Path。由于方法比较多,我这里分组来讲下。

moveTo , lineTo , setLastPoint , close

先创建画笔:

<code class="hljs avrasm has-numbering">        paint = new Paint()<span class="hljs-comment">;</span>
        paint<span class="hljs-preprocessor">.setAntiAlias</span>(true)<span class="hljs-comment">;</span>
        paint<span class="hljs-preprocessor">.setStyle</span>(Paint<span class="hljs-preprocessor">.Style</span><span class="hljs-preprocessor">.STROKE</span>)<span class="hljs-comment">;</span>
        paint<span class="hljs-preprocessor">.setStrokeWidth</span>(<span class="hljs-number">10</span>)<span class="hljs-comment">;</span>
        paint<span class="hljs-preprocessor">.setColor</span>(Color<span class="hljs-preprocessor">.parseColor</span>(<span class="hljs-string">"#FF0000"</span>))<span class="hljs-comment">;</span></code>

注意paint.setStyle(Paint.Style.FILL);,设置画笔为实心。一些线条将在画布上看不见。

1、lineTo

首先我们来看看lineTo,如果你直接moveTo 将看不出效果。

<code class="hljs avrasm has-numbering">        Path path = new Path()<span class="hljs-comment">;</span>

        path<span class="hljs-preprocessor">.lineTo</span>(<span class="hljs-number">200</span>,<span class="hljs-number">200</span>)<span class="hljs-comment">;</span>
        path<span class="hljs-preprocessor">.lineTo</span>(<span class="hljs-number">400</span>,<span class="hljs-number">0</span>)<span class="hljs-comment">;</span>

        canvas<span class="hljs-preprocessor">.drawPath</span>(path,paint)<span class="hljs-comment">;</span></code>

path

为了方便大家好观察坐标的变化,我在屏幕上画出了网格,每块网格的宽高都是100。由于第一次之前没有过操作,所以默认点就是原点(屏幕左上角),第一次lineTo就是坐标原点到(200,200)之间的直线。第二次lineTo就是上一次结束点位置(200,200)到(400,0)点之间的直线。

2、moveTo 和setLastPoint

方法预览:

<code class="hljs cs has-numbering">moveTo(<span class="hljs-keyword">float</span> x, <span class="hljs-keyword">float</span> y) 

setLastPoint(<span class="hljs-keyword">float</span> dx, <span class="hljs-keyword">float</span> dy)</code>

这两个方法在作用上有相似之处,却是两个不同的东西,具体参考下表:

方法名作用是否影响之前的操作是否影响之后的操作
moveTo移动下一次操作的起点位置
setLastPoint改变上一次操作点的位置

来看看下面的例子:

<code class="hljs avrasm has-numbering">        Path path = new Path()<span class="hljs-comment">;</span>

        path<span class="hljs-preprocessor">.lineTo</span>(<span class="hljs-number">200</span>, <span class="hljs-number">200</span>)<span class="hljs-comment">;</span>
        path<span class="hljs-preprocessor">.moveTo</span>(<span class="hljs-number">300</span>,<span class="hljs-number">300</span>)<span class="hljs-comment">;</span>
        path<span class="hljs-preprocessor">.lineTo</span>(<span class="hljs-number">400</span>, <span class="hljs-number">0</span>)<span class="hljs-comment">;</span>

        canvas<span class="hljs-preprocessor">.drawPath</span>(path, paint)<span class="hljs-comment">;</span></code>

效果图:

path

<code class="hljs avrasm has-numbering">        Path path = new Path()<span class="hljs-comment">;</span>

        path<span class="hljs-preprocessor">.lineTo</span>(<span class="hljs-number">200</span>, <span class="hljs-number">200</span>)<span class="hljs-comment">;</span>
        path<span class="hljs-preprocessor">.setLastPoint</span>(<span class="hljs-number">300</span>,<span class="hljs-number">100</span>)<span class="hljs-comment">;</span>
        path<span class="hljs-preprocessor">.lineTo</span>(<span class="hljs-number">400</span>, <span class="hljs-number">0</span>)<span class="hljs-comment">;</span>

        canvas<span class="hljs-preprocessor">.drawPath</span>(path, paint)<span class="hljs-comment">;</span></code>

效果图:

path

当我们绘制线条之前,调用moveTosetLastPoint效果是一样的,都是对坐标原点(0,0)进行操作。setLastPoint是重置上一次操作的最后一点,在执行完第一次lineTo的时候,最后一个点就是(200,200),setLastPoint更改(200,200)为(300,100),所以在执行的时候就是(300,100)到(400, 0)之间的连线了。

3、close

方法预览

<code class="hljs cs has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">close</span>()</code>

close方法连接最后一个点和最初一个点(如果两个点不重合)形成一个闭合的图形。

<code class="hljs avrasm has-numbering">        path<span class="hljs-preprocessor">.moveTo</span>(<span class="hljs-number">100</span>,<span class="hljs-number">100</span>)<span class="hljs-comment">;</span>
        path<span class="hljs-preprocessor">.lineTo</span>(<span class="hljs-number">500</span>,<span class="hljs-number">100</span>)<span class="hljs-comment">;</span>
        path<span class="hljs-preprocessor">.lineTo</span>(<span class="hljs-number">300</span>,<span class="hljs-number">400</span>)<span class="hljs-comment">;</span>
        path<span class="hljs-preprocessor">.close</span>()<span class="hljs-comment">;</span>
        canvas<span class="hljs-preprocessor">.drawPath</span>(path, paint)<span class="hljs-comment">;</span></code>

效果图:

path

上图中可以看到lineTo(500,100)直线和lineTo(300,400)直线,而close方法就是连接(300,400),(100,100)两点,形成一个闭合的区域。

注意:close的作用的封闭路径,如果连接最后一个点和最初一个点任然无法形成闭合的区域,那么close什么也不做。

quadTo,cubicTo

二次贝塞尔曲线以及三次贝塞尔曲线。

1、quadTo

方法预览

<code class="hljs cs has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">quadTo</span>(<span class="hljs-keyword">float</span> x1, <span class="hljs-keyword">float</span> y1, <span class="hljs-keyword">float</span> x2, <span class="hljs-keyword">float</span> y2)</code>

quadTo方法其中 (x1,y1) 为控制点,(x2,y2)为结束点。

<code class="hljs avrasm has-numbering">        path<span class="hljs-preprocessor">.moveTo</span>(<span class="hljs-number">100</span>,<span class="hljs-number">400</span>)<span class="hljs-comment">;</span>
        path<span class="hljs-preprocessor">.quadTo</span>(<span class="hljs-number">300</span>, <span class="hljs-number">100</span>, <span class="hljs-number">400</span>, <span class="hljs-number">400</span>)<span class="hljs-comment">;</span>

        canvas<span class="hljs-preprocessor">.drawPath</span>(path, paint)<span class="hljs-comment">;</span></code>

效果图:

path

2、cubicTo

方法预览:

<code class="hljs cs has-numbering"><span class="hljs-keyword">pub</span></code>

cubicTo方法比quadTo方法多了一个点坐标,那么其中(x1,y1) 为控制点,(x2,y2)为控制点,(x3,y3) 为结束点。

<code class="hljs avrasm has-numbering">        path<span class="hljs-preprocessor">.moveTo</span>(<span class="hljs-number">100</span>, <span class="hljs-number">400</span>)<span class="hljs-comment">;</span>
        path<span class="hljs-preprocessor">.cubicTo</span>(<span class="hljs-number">100</span>, <span class="hljs-number">400</span>, <span class="hljs-number">300</span>, <span class="hljs-number">100</span>, <span class="hljs-number">400</span>, <span class="hljs-number">400</span>)<span class="hljs-comment">;</span>

        canvas<span class="hljs-preprocessor">.drawPath</span>(path, paint)<span class="hljs-comment">;</span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul>

绘制的图形和上面的quadTo绘制的图形是一样的。我们去掉moveTo来看看运行的效果图:

path

如果你想了解贝塞尔曲线公式,请链接这里

addXxx和arcTo

主要是向Path中添加基本图形以及区分addArcarcTo

1、添加基本图形

方法预览:

<code class="hljs rust has-numbering"><span class="hljs-comment">//圆形</span>
addCircle(<span class="hljs-keyword">float</span> x, <span class="hljs-keyword">float</span> y, <span class="hljs-keyword">float</span> radius, Path.Direction <span class="hljs-keyword">dir</span>)
<span class="hljs-comment">//椭圆</span>
addOval(RectF oval, Path.Direction <span class="hljs-keyword">dir</span>)
addOval(<span class="hljs-keyword">float</span> left, <span class="hljs-keyword">float</span> top, <span class="hljs-keyword">float</span> right, <span class="hljs-keyword">float</span> bottom, Path.Direction <span class="hljs-keyword">dir</span>)
<span class="hljs-comment">//矩形</span>
addRect(RectF rect, Path.Direction <span class="hljs-keyword">dir</span>)
addRect(<span class="hljs-keyword">float</span> left, <span class="hljs-keyword">float</span> top, <span class="hljs-keyword">float</span> right, <span class="hljs-keyword">float</span> bottom, Path.Direction <span class="hljs-keyword">dir</span>)
<span class="hljs-comment">//圆角矩形</span>
addRoundRect(RectF rect, <span class="hljs-keyword">float</span> rx, <span class="hljs-keyword">float</span> ry, Path.Direction <span class="hljs-keyword">dir</span>) 
addRoundRect(<span class="hljs-keyword">float</span> left, <span class="hljs-keyword">float</span> top, <span class="hljs-keyword">float</span> right, <span class="hljs-keyword">float</span> bottom, <span class="hljs-keyword">float</span> rx, <span class="hljs-keyword">float</span> ry, Path.Direction <span class="hljs-keyword">dir</span>)
addRoundRect(RectF rect, <span class="hljs-keyword">float</span>[] radii, Path.Direction <span class="hljs-keyword">dir</span>)
addRoundRect(<span class="hljs-keyword">float</span> left, <span class="hljs-keyword">float</span> top, <span class="hljs-keyword">float</span> right, <span class="hljs-keyword">float</span> bottom, <span class="hljs-keyword">float</span>[] radii, Path.Direction <span class="hljs-keyword">dir</span>)</code>

我们仔细观察上面的方法,在最后都有一个Path.Direction,这是个什么东东呢?Direction的意思是方向,指导,趋势。点进去跟一下你会发现Direction是一个枚举类型(Enum)分别有CW(顺时针),CCW(逆时针)两个常量。那么它的作用主要有以下两点:

序号作用
1在添加图形时确定闭合顺序(各个点的记录顺序)
2对自相交图形的渲染结果有影响

我们先来看看闭合顺序的问题,添加一个矩形看看:

<code class="hljs avrasm has-numbering">        path<span class="hljs-preprocessor">.addRect</span>(<span class="hljs-number">100</span>, <span class="hljs-number">200</span>, <span class="hljs-number">500</span>, <span class="hljs-number">400</span>, Path<span class="hljs-preprocessor">.Direction</span><span class="hljs-preprocessor">.CW</span>)<span class="hljs-comment">;</span>

        canvas<span class="hljs-preprocessor">.drawPath</span>(path, paint)<span class="hljs-comment">;</span></code>

path

我将上面的代码CW改成CCW再运行一次,结果一模一样,尼玛区别在哪里啊。稍安勿躁,想看到区别就要用到setLastPoint(重置最后一个点的坐标)。我们来这样变变代码:

<code class="hljs avrasm has-numbering">        path<span class="hljs-preprocessor">.addRect</span>(<span class="hljs-number">100</span>, <span class="hljs-number">200</span>, <span class="hljs-number">500</span>, <span class="hljs-number">400</span>, Path<span class="hljs-preprocessor">.Direction</span><span class="hljs-preprocessor">.CW</span>)<span class="hljs-comment">;</span>
        path<span class="hljs-preprocessor">.setLastPoint</span>(<span class="hljs-number">200</span>,<span class="hljs-number">400</span>)<span class="hljs-comment">;</span>

        canvas<span class="hljs-preprocessor">.drawPath</span>(path, paint)<span class="hljs-comment">;</span></code>

效果立马现行:

path

为什么图形会发生奇怪的变化呢。我们先来分析一下,绘制一个矩形至少需要对角线的两个点,根据这两个点计算出四条边然后把四条边按照顺序连接起来。上图的起始坐标是(100,200)按着顺时针的方向连接(500,200),(500,400),(100,400)最后连接(100,200)形成一个矩形。setLastPoint是重置上一个操作点坐标及改变(100,400)为(200,400),所以出现了上图的效果。

接下来我们看看逆时针的情况:

<code class="hljs avrasm has-numbering">        path<span class="hljs-preprocessor">.addRect</span>(<span class="hljs-number">100</span>, <span class="hljs-number">200</span>, <span class="hljs-number">500</span>, <span class="hljs-number">400</span>, Path<span class="hljs-preprocessor">.Direction</span><span class="hljs-preprocessor">.CCW</span>)<span class="hljs-comment">;</span>
        path<span class="hljs-preprocessor">.setLastPoint</span>(<span class="hljs-number">400</span>,<span class="hljs-number">300</span>)<span class="hljs-comment">;</span>

        canvas<span class="hljs-preprocessor">.drawPath</span>(path, paint)<span class="hljs-comment">;</span></code>

效果图:

path

我们理清楚了闭合的问题,相交问题与设置填充模式有关。

我以addCircle方法来讲解添加图形,并不会逐一讲解。

<code class="hljs avrasm has-numbering">        path<span class="hljs-preprocessor">.addCircle</span>(<span class="hljs-number">300</span>,<span class="hljs-number">300</span>,<span class="hljs-number">200</span>, Path<span class="hljs-preprocessor">.Direction</span><span class="hljs-preprocessor">.CW</span>)<span class="hljs-comment">;</span>

        canvas<span class="hljs-preprocessor">.drawPath</span>(path, paint)<span class="hljs-comment">;</span></code>

path

绘制圆形,(300,300)点表示圆心坐标,200 表示半径长度。

2、addPath

方法预览:

<code class="hljs cs has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">addPath</span>(Path src)
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">addPath</span>(Path src, <span class="hljs-keyword">float</span> dx, <span class="hljs-keyword">float</span> dy)
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">addPath</span>(Path src, Matrix matrix)</code>

addPath方法就是将两个路径合并到一起。第二个方法的dx,dy指的是偏移量,第三个方法是添加到当前path之前先使用Matrix进行变换。来看看下面例子:

<code class="hljs mathematica has-numbering">        <span class="hljs-keyword">Path</span> path = new <span class="hljs-keyword">Path</span>();
        path.addRect(<span class="hljs-number">100</span>,<span class="hljs-number">100</span>,<span class="hljs-number">400</span>,<span class="hljs-number">300</span>, <span class="hljs-keyword">Path</span>.<span class="hljs-keyword">Direction</span>.CW);

        <span class="hljs-keyword">Path</span> src=new <span class="hljs-keyword">Path</span>();
        src.addCircle(<span class="hljs-number">300</span>,<span class="hljs-number">300</span>,<span class="hljs-number">100</span>, <span class="hljs-keyword">Path</span>.<span class="hljs-keyword">Direction</span>.CW);
        path.addPath(src,<span class="hljs-number">0</span>,<span class="hljs-number">100</span>);

        canvas.drawPath(path, paint);</code>

效果图:

path

3、addArc与arcTo

方法预览:

<code class="hljs java has-numbering">addArc(RectF oval, <span class="hljs-keyword">float</span> startAngle, <span class="hljs-keyword">float</span> sweepAngle)
addArc(<span class="hljs-keyword">float</span> left, <span class="hljs-keyword">float</span> top, <span class="hljs-keyword">float</span> right, <span class="hljs-keyword">float</span> bottom, <span class="hljs-keyword">float</span> startAngle, <span class="hljs-keyword">float</span> sweepAngle)

arcTo(RectF oval, <span class="hljs-keyword">float</span> startAngle, <span class="hljs-keyword">float</span> sweepAngle)
arcTo(RectF oval, <span class="hljs-keyword">float</span> startAngle, <span class="hljs-keyword">float</span> sweepAngle, <span class="hljs-keyword">boolean</span> forceMoveTo)
arcTo(<span class="hljs-keyword">float</span> left, <span class="hljs-keyword">float</span> top, <span class="hljs-keyword">float</span> right, <span class="hljs-keyword">float</span> bottom, <span class="hljs-keyword">float</span> startAngle, <span class="hljs-keyword">float</span> sweepAngle, <span class="hljs-keyword">boolean</span> forceMoveTo)</code>

从方法名字上面看,这两个方法都是与圆弧有关,那么他们之间肯定是有区别的:

名称作用区别
addArc添加一个圆弧到Path直接添加一个圆弧到path中,和上一次操作点无关
arcTo添加一个圆弧到Path添加一个圆弧到path中,如果圆弧的起点和上次操作点坐标不同就连接两个点

startAngle表示开始圆弧度数(0度与X轴方向对齐,顺时针移动,弧度增大)。

注意:sweepAngle表示运动了多少弧度,并不是结束弧度。

forceMoveTo表示“是否强制使用moveTo”,也就是说是否使用moveTo将上一次操作点移动到圆弧的起点坐标。默认是false。

forceMoveTo含义
true将最后一个点移动到圆弧起点,即不连接最后一个点与圆弧起点
false不移动,而是连接最后一个点与圆弧起点(注意之前没有操作的话,不会连接原点)

示例:

<code class="hljs avrasm has-numbering">        path<span class="hljs-preprocessor">.lineTo</span>(<span class="hljs-number">200</span>, <span class="hljs-number">200</span>)<span class="hljs-comment">;</span>
        RectF rectF = new RectF(<span class="hljs-number">100</span>, <span class="hljs-number">100</span>, <span class="hljs-number">400</span>, <span class="hljs-number">400</span>)<span class="hljs-comment">;</span>
        path<span class="hljs-preprocessor">.arcTo</span>(rectF, <span class="hljs-number">0</span>, <span class="hljs-number">270</span>, true)<span class="hljs-comment">;</span>
        // path<span class="hljs-preprocessor">.addArc</span>(rectF,<span class="hljs-number">0</span>,<span class="hljs-number">270</span>)<span class="hljs-comment">;和上面一句等价</span>

        canvas<span class="hljs-preprocessor">.drawPath</span>(path, paint)<span class="hljs-comment">;</span></code>

效果图:

path

我们把 path.arcTo(rectF, 0, 270, true);改成 path.arcTo(rectF, 0, 270, false);,来看看效果图:

path

从上面两张图可以看出明显的变化。

isEmpty、 isRect、 set 和 offset

isEmpty

判断path中是否包含内容。

<code class="hljs avrasm has-numbering">        Path path = new Path()<span class="hljs-comment">;</span>
        Log<span class="hljs-preprocessor">.e</span>(<span class="hljs-string">"-----"</span>,<span class="hljs-string">"----"</span>+path<span class="hljs-preprocessor">.isEmpty</span>())<span class="hljs-comment">;//-----: ----true</span>
        path<span class="hljs-preprocessor">.lineTo</span>(<span class="hljs-number">100</span>,<span class="hljs-number">100</span>)<span class="hljs-comment">;</span>
        Log<span class="hljs-preprocessor">.e</span>(<span class="hljs-string">"-----"</span>,<span class="hljs-string">"----"</span>+path<span class="hljs-preprocessor">.isEmpty</span>())<span class="hljs-comment">;//-----: ----false</span>

        canvas<span class="hljs-preprocessor">.drawPath</span>(path, paint)<span class="hljs-comment">;</span></code>

isRect

方法预览:

<code class="hljs erlang has-numbering"><span class="hljs-function"><span class="hljs-title">isRect</span><span class="hljs-params">(<span class="hljs-variable">RectF</span> rect)</span></span></code><ul style="" class="pre-numbering"><li>1</li></ul><ul style="" class="pre-numbering"><li>1</li></ul>

判断path是否是一个矩形,如果是一个矩形的话,会将矩形的信息存放进参数rect中。

<code class="hljs avrasm has-numbering">        Path path = new Path()<span class="hljs-comment">;</span>
        RectF rectF = new RectF()<span class="hljs-comment">;</span>
        rectF<span class="hljs-preprocessor">.left</span> = <span class="hljs-number">100</span><span class="hljs-comment">;</span>
        rectF<span class="hljs-preprocessor">.top</span> = <span class="hljs-number">100</span><span class="hljs-comment">;</span>
        rectF<span class="hljs-preprocessor">.right</span> = <span class="hljs-number">400</span><span class="hljs-comment">;</span>
        rectF<span class="hljs-preprocessor">.bottom</span> = <span class="hljs-number">300</span><span class="hljs-comment">;</span>
        path<span class="hljs-preprocessor">.addRect</span>(rectF, Path<span class="hljs-preprocessor">.Direction</span><span class="hljs-preprocessor">.CW</span>)<span class="hljs-comment">;</span>
        boolean isRect = path<span class="hljs-preprocessor">.isRect</span>(rectF)<span class="hljs-comment">;</span>
        Log<span class="hljs-preprocessor">.e</span>(<span class="hljs-string">"-----"</span>,<span class="hljs-string">"------"</span>+isRect)<span class="hljs-comment">;//-----: ------true</span></code>

set

方法预览:

<code class="hljs cs has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">set</span>(Path src)</code>

将新的path赋值到现有path。相当于运算符中的“=”,如a=b,把b赋值给a

还是一起来看个例子:

<code class="hljs mathematica has-numbering">        <span class="hljs-keyword">Path</span> path = new <span class="hljs-keyword">Path</span>();
        path.addRect(<span class="hljs-number">100</span>,<span class="hljs-number">100</span>,<span class="hljs-number">400</span>,<span class="hljs-number">300</span>, <span class="hljs-keyword">Path</span>.<span class="hljs-keyword">Direction</span>.CW);
        <span class="hljs-keyword">Path</span> src=new <span class="hljs-keyword">Path</span>();
        src.addCircle(<span class="hljs-number">300</span>,<span class="hljs-number">200</span>,<span class="hljs-number">100</span>, <span class="hljs-keyword">Path</span>.<span class="hljs-keyword">Direction</span>.CW);
        path.set(src);
        canvas.drawPath(path, paint);</code>

效果图:

path

offset

方法预览:

<code class="hljs cs has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">offset</span>(<span class="hljs-keyword">float</span> dx, <span class="hljs-keyword">float</span> dy)
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">offset</span>(<span class="hljs-keyword">float</span> dx, <span class="hljs-keyword">float</span> dy, Path dst)</code>

这个方法就是对Path进行一段平移,正方向和X轴,Y轴方向一致(如果dx为正数则向右平移,反之向左平移;如果dy为正则向下平移,反之向上平移)。我们看到第二个方法多了一个dst,这个又是一个什么玩意呢,其实参数das是存储平移后的path的。

用例子来说明一下:

<code class="hljs mathematica has-numbering">        <span class="hljs-keyword">Path</span> path = new <span class="hljs-keyword">Path</span>();
        path.addCircle(<span class="hljs-number">300</span>, <span class="hljs-number">200</span>, <span class="hljs-number">100</span>, <span class="hljs-keyword">Path</span>.<span class="hljs-keyword">Direction</span>.CW);

        <span class="hljs-keyword">Path</span> dst = new <span class="hljs-keyword">Path</span>();
        dst.addCircle(<span class="hljs-number">500</span>, <span class="hljs-number">200</span>, <span class="hljs-number">200</span>, <span class="hljs-keyword">Path</span>.<span class="hljs-keyword">Direction</span>.CW);

        path.offset(-<span class="hljs-number">100</span>, <span class="hljs-number">100</span>, dst);
        canvas.drawPath(path, paint);</code>

效果图:

path

从运行效果图可以看出,虽然我们在dst中添加了一个圆形,但是并没有表现出来,所以,当dst中存在内容时,dst中原有的内容会被清空,而存放平移后的path。

FillType

方法预览:

<code class="hljs cs has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setFillType</span>(Path.FillType ft)
<span class="hljs-keyword">public</span> Path.FillType <span class="hljs-title">getFillType</span>()</code>

setFillType方法中的参数Path.FillType为枚举类型:

FillType值含义
FillType.WINDING取path所有所在区域 默认值
FillType.EVEN_ODD取path所在并不相交区域
FillType.INVERSE_WINDING取path所有未占区域
FillType.INVERSE_EVEN_ODD取path未占或相交区域

path所在区域
path所在区域
path所在区域

setFillType

WINDING

<code class="hljs avrasm has-numbering">        Path path = new Path()<span class="hljs-comment">;</span>
        path<span class="hljs-preprocessor">.addCircle</span>(<span class="hljs-number">300</span>,<span class="hljs-number">200</span>,<span class="hljs-number">100</span>, Path<span class="hljs-preprocessor">.Direction</span><span class="hljs-preprocessor">.CW</span>)<span class="hljs-comment">;</span>
        path<span class="hljs-preprocessor">.addCircle</span>(<span class="hljs-number">200</span>,<span class="hljs-number">200</span>,<span class="hljs-number">100</span>, Path<span class="hljs-preprocessor">.Direction</span><span class="hljs-preprocessor">.CW</span>)<span class="hljs-comment">;</span>
        path<span class="hljs-preprocessor">.setFillType</span>(Path<span class="hljs-preprocessor">.FillType</span><span class="hljs-preprocessor">.WINDING</span>)<span class="hljs-comment">;</span>
        canvas<span class="hljs-preprocessor">.drawPath</span>(path, paint)<span class="hljs-comment">;</span></code>

效果图:

path

EVEN_ODD

代码我就不贴了,直接上图(上mis):

path

INVERSE_WINDING

path

INVERSE_EVEN_ODD

path

isInverseFillType

是否是逆填充模式:WINDING 和 EVEN_ODD 返回false;
INVERSE_WINDING 和 INVERSE_EVEN_ODD 返回true;

toggleInverseFillType

切换相反的填充模式,如果填充模式为WINDING则填充模式为INVERSE_WINDING,反之为WINDING模式;如果填充模式为EVEN_ODD则填充模式为INVERSE_EVEN_ODD,反之为EVEN_ODD模式。

举个例子:

<code class="hljs avrasm has-numbering">        Path path = new Path()<span class="hljs-comment">;</span>
        path<span class="hljs-preprocessor">.addCircle</span>(<span class="hljs-number">300</span>,<span class="hljs-number">200</span>,<span class="hljs-number">100</span>, Path<span class="hljs-preprocessor">.Direction</span><span class="hljs-preprocessor">.CW</span>)<span class="hljs-comment">;</span>
        path<span class="hljs-preprocessor">.addCircle</span>(<span class="hljs-number">200</span>,<span class="hljs-number">200</span>,<span class="hljs-number">100</span>, Path<span class="hljs-preprocessor">.Direction</span><span class="hljs-preprocessor">.CW</span>)<span class="hljs-comment">;</span>
        path<span class="hljs-preprocessor">.setFillType</span>(Path<span class="hljs-preprocessor">.FillType</span><span class="hljs-preprocessor">.INVERSE</span>_EVEN_ODD)<span class="hljs-comment">;</span>
        path<span class="hljs-preprocessor">.toggleInverseFillType</span>()<span class="hljs-comment">;</span>
        canvas<span class="hljs-preprocessor">.drawPath</span>(path, paint)<span class="hljs-comment">;</span></code>

效果图和上面EVEN_ODD模式一模一样。

path

以上是关于Android自定义视图 View 之重要知识点 Path 详解的主要内容,如果未能解决你的问题,请参考以下文章

Android组件体系之视图绘制

Android进阶之自定义View实战仿iOS UISwitch控件实现

Android进阶之自定义View实战仿iOS UISwitch控件实现

Android 自定义View流程解析

Android中初步自定义view

android 自定义view之侧滑效果