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,rCubicTo rXxx方法 不带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>

为了方便大家好观察坐标的变化,我在屏幕上画出了网格,每块网格的宽高都是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>

效果图:

<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>

效果图:

当我们绘制线条之前,调用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>

效果图:

上图中可以看到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>

效果图:

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来看看运行的效果图:

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

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>

我将上面的代码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>

效果立马现行:

为什么图形会发生奇怪的变化呢。我们先来分析一下,绘制一个矩形至少需要对角线的两个点,根据这两个点计算出四条边然后把四条边按照顺序连接起来。上图的起始坐标是(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>

效果图:

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

我以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>

绘制圆形,(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>

效果图:

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.arcTo(rectF, 0, 270, true);改成 path.arcTo(rectF, 0, 270, false);,来看看效果图:

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

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>

效果图:

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>

效果图:

从运行效果图可以看出,虽然我们在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>

效果图:

EVEN_ODD

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

INVERSE_WINDING

INVERSE_EVEN_ODD

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模式一模一样。

时间: 2024-10-02 00:10:50

Android自定义视图 View 之重要知识点 Path 详解的相关文章

【转】ANDROID自定义视图——onLayout源码 流程 思路详解

转载(http://blog.csdn.net/a396901990) 简介: 在自定义view的时候,其实很简单,只需要知道3步骤: 1.测量——onMeasure():决定View的大小 2.布局——onLayout():决定View在ViewGroup中的位置 3.绘制——onDraw():如何绘制这个View. 而第3步的onDraw系统已经封装的很好了,基本不用我们来操心,只需要专注到1,2两个步骤就中好了. 第一步的测量,可以参考我之前的文章:(ANDROID自定义视图——onMea

Android中自定义视图View之---Canvas和Path对象

介绍Android中的Paint和Canvas的概念和使用方法 Android中的Paint和Canvas的概念是很简单的,就是我们用画笔在画布上进行绘制没什么难度的,我们只要拿到画笔Paint和画布Canvas对象就可以进行操作了.当然Canvas对象提供了很多绘制图形的方法,下面来看一下代码吧: package com.example.drawpathdemo; import android.annotation.SuppressLint; import android.content.Co

ANDROID自定义视图——仿瀑布布局(附源码)

简介: 在自定义view的时候,其实很简单,只需要知道3步骤: 1.测量--onMeasure():决定View的大小 2.布局--onLayout():决定View在ViewGroup中的位置 3.绘制--onDraw():如何绘制这个View. 第3步的onDraw系统已经封装的很好了,基本不用我们来操心,只需要专注到1,2两个步骤就中好了. 第一步的测量,可以参考:(ANDROID自定义视图--onMeasure,MeasureSpec源码 流程 思路详解) 第二步的布局,可以参考:(AN

【转】ANDROID自定义视图——onMeasure,MeasureSpec源码 流程 思路详解

原文地址:http://blog.csdn.net/a396901990/article/details/36475213 简介: 在自定义view的时候,其实很简单,只需要知道3步骤: 1.测量——onMeasure():决定View的大小 2.布局——onLayout():决定View在ViewGroup中的位置 3.绘制——onDraw():如何绘制这个View. 而第3步的onDraw系统已经封装的很好了,基本不用我们来操心,只需要专注到1,2两个步骤就中好了. 而这篇文章就来谈谈第一步

Android中自定义视图View之---进阶篇(Canvas的使用)

更多技术内容请移步:我的个人博客 一.前言 今天是周日,昨天刚刚写完了一篇关于如何搭建LNMP环境,让自己可以DIY有个性的个人主页: http://blog.csdn.net/jiangwei0910410003/article/details/50929955 那么今天,我们继续来看一篇关于Android中的UI篇,如何自定义视图View的进阶篇,关于前奏篇之前已经写过了,还没有了解的同学可以去看看:http://blog.csdn.net/jiangwei0910410003/articl

Android中自定义视图View之---前奏篇

前言 好长时间没写blog了,心里感觉有点空荡荡的,今天有时间就来写一个关于自定义视图的的blog吧.关于这篇blog,网上已经有很多案例了,其实没什么难度的.但是我们在开发的过程中有时候会用到一些自定义的View以达到我们所需要的效果.其实网上的很多案例我们看完之后,发现这部分没什么难度的,我总结了两点: 1.准备纸和笔,计算坐标 2.在onDraw方法中开始画图,invalidate方法刷新,onTouchEvent方法监听触摸事件 对于绘图相关的知识,之前在弄JavaSE相关的知识的时候,

Android中自定义视图View之---开发案例

自定义视图View的案例 下面我们就是开始正式的进入自定义视图View了 在讲解正式内容之前,我们先来看一下基本知识 1.我们在自定义视图View的时候正确的步骤和方法 1).必须定义有Context/Attrbuite参数的构造方法,并且调用父类的方法 public LabelView(Context context, AttributeSet attrs) 不然会报错: 2).重写onMeasure方法 @Override protected void onMeasure(int width

onLayout源码 流程 思路详解(ANDROID自定义视图)

简介: 在自定义view的时候,其实很简单,只需要知道3步骤: 1.测量--onMeasure():决定View的大小 2.布局--onLayout():决定View在ViewGroup中的位置 3.绘制--onDraw():如何绘制这个View. 而第3步的onDraw系统已经封装的很好了,基本不用我们来操心,只需要专注到1,2两个步骤就中好了. 第一步的测量,可以参考我之前的文章:(ANDROID自定义视图--onMeasure流程,MeasureSpec详解) 而这篇文章就来谈谈第二步:"

Android自定义视图教程

Android自定义视图教程 Android的UI元素都是基于View(屏幕中单个元素)和ViewGroup(元素的集合),Android有许多自带的组件和布局,比如Button.TextView.RelativeLayout.在app开发过程中我们需要自定义视图组件来满足我们的需求.通过继承自View或者View的子类,覆写onDraw或者onTouchEvent等方法来覆盖视图的行为. 创建完全自定义的组件 创建自定义的组件主要围绕着以下五个方面: 绘图(Drawing): 控制视图的渲染,