我们在做自定义View的时候,很多时候都会用到Path,即路径,今天总结一下Path有哪些,以及他们的常用方法。

Path常用方法:

方法

作用

备注

moveTo

移动起点

移动下一次操作的起点位置

lineTo

连接直线

连接上一个点到当前点之间的直线

setLastPoint

设置终点

重置最后一个点的位置

close

闭合路径

从最后一个点连接最初的一个点,形成一个闭合区域

addRect

添加矩形

添加矩形到当前Path

addRoundRect

添加圆角矩形

添加圆角矩形到当前Path

addOval

添加椭圆

添加椭圆到当前Path

addCircle

添加圆

addPath

添加路径

addArc

添加圆弧

arcTo

绘制圆弧

附加到路径中

isEmpty

是否为空

isRect

是否为矩形

set

替换路劲

用新的路劲替换当前路劲的所有内容

offset

偏移路劲

对当前的路劲进行偏移

quadTo

贝塞尔曲线

二次贝塞尔曲线的方法

cubicTo

贝塞尔曲线

三次贝塞尔曲线的方法

rMoveTo,rlineTo,rQuadTo,rCubicTo

不带r的方法是基于原点坐标系(偏移量),带r的基于当前点坐标系(偏移量)

op

布尔操作

对两个Path进行布尔运算(交集,并集)等操作

setFillType

填充模式

设置Path的填充模式

getFillType

填充模式

获取Path的填充模式

isInverseFillType

是否逆填充

判断是否是逆填充模式

toggleInverseFillType

相反模式

切换相反的填充模式

incReserve

提示方法

提示Path还有多少个点等待加入

computeBounds

计算边界

计算Path的路劲

reset,rewind

重置路劲

清除Path中的内容(reset相当于new Path , rewind 会保留Path的数据结构)

transform

矩阵操作

矩阵变换

Path方法使用详解:

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

Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(10);
        paint.setColor(Color.parseColor("#FF0000"));

1、lineTo

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

Path path = new Path();
    path.lineTo(200,200);
    path.lineTo(400,0);

    canvas.drawPath(path,paint);




Android开发之Path详解 安卓path_path


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

2、moveTo 和setLastPoint

moveTo(float x, float y) 

setLastPoint(float dx, float dy)

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

方法名

作用

是否影响之前的操作

是否影响之后的操作

moveTo

移动下一次操作的起点位置



setLastPoint

改变上一次操作点的位置




来看看下面的例子:

Path path = new Path();
        path.lineTo(200, 200);
        path.moveTo(300,300);
        path.lineTo(400, 0);
        canvas.drawPath(path, paint);



Android开发之Path详解 安卓path_移动_02


Path path = new Path();
        path.lineTo(200, 200);
        path.setLastPoint(300,100);
        path.lineTo(400, 0);
        canvas.drawPath(path, paint);



Android开发之Path详解 安卓path_Android开发之Path详解_03


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

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

path.moveTo(100,100);
        path.lineTo(500,100);
        path.lineTo(300,400);
        path.close();
        canvas.drawPath(path, paint);



Android开发之Path详解 安卓path_贝塞尔曲线_04


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

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

quadTo,cubicTo
二次贝塞尔曲线以及三次贝塞尔曲线。

1、quadTo

public void quadTo(float x1, float y1, float x2, float y2)

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

path.moveTo(100,400);
        path.quadTo(300, 100, 400, 400);
        canvas.drawPath(path, paint);



Android开发之Path详解 安卓path_Android开发之Path详解_05


2、cubicTo

public void cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)

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

path.moveTo(100, 400);
        path.cubicTo(100, 400, 300, 100, 400, 400);
        canvas.drawPath(path, paint);

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



Android开发之Path详解 安卓path_Android开发之Path详解_06


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

addXxx和arcTo

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

1、添加基本图形

各个添加基本图形的方法参数中,有一个Path.Direction dir。这是个什么东东呢?Direction的意思是方向,指导,趋势。点进去跟一下你会发现Direction是一个枚举类型(Enum)分别有CW(顺时针),CCW(逆时针)两个常量。那么它的作用主要有以下两点:

1.在添加图形时确定闭合顺序(各个点的记录顺序)

        2.对自相交图形的渲染结果有影响

2、addPath

public void addPath(Path src)
    public void addPath(Path src, float dx, float dy)
    public void addPath(Path src, Matrix matrix)

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

Path path = new Path();
        path.addRect(100,100,400,300, Path.Direction.CW);
        Path src=new Path();
        src.addCircle(300,300,100, Path.Direction.CW);
        path.addPath(src,0,100);
        canvas.drawPath(path, paint);



Android开发之Path详解 安卓path_Android开发之Path详解_07


3、addArc与arcTo

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

addArc 添加一个圆弧到Path 直接添加一个圆弧到path中,和上一次操作点无关

arcTo 添加一个圆弧到Path 添加一个圆弧到path中,如果圆弧的起点和上次操作点坐标不同就连接两个点

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

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

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

forceMoveTo

含义

true

将最后一个点移动到圆弧起点,即不连接最后一个点与圆弧起点

false

不移动,而是连接最后一个点与圆弧起点(注意之前没有操作的话,不会连接原点)

示例:

path.lineTo(200, 200);
        RectF rectF = new RectF(100, 100, 400, 400);
        path.arcTo(rectF, 0, 270, true);
        // path.addArc(rectF,0,270);和上面一句等价
        canvas.drawPath(path, paint);



Android开发之Path详解 安卓path_贝塞尔曲线_08


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



Android开发之Path详解 安卓path_path_09


offset

public void offset(float dx, float dy)
public void offset(float dx, float dy, Path dst)

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

FillType

public void setFillType(Path.FillType ft)
public Path.FillType getFillType()

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

FillType值

含义

FillType.WINDING

取path所有所在区域 默认值

FillType.EVEN_ODD

取path所在并不相交区域

FillType.INVERSE_WINDING

取path所有未占区域

FillType.INVERSE_EVEN_ODD

取path未占或相交区域

下面通过几个实例说明:

setFillType

WINDING:
        Path path = new Path();
        path.addCircle(300,200,100, Path.Direction.CW);
        path.addCircle(200,200,100, Path.Direction.CW);
        path.setFillType(Path.FillType.WINDING);
        canvas.drawPath(path, paint);



Android开发之Path详解 安卓path_android_10


EVEN_ODD:



Android开发之Path详解 安卓path_android_11


INVERSE_WINDING:



Android开发之Path详解 安卓path_android_12


INVERSE_EVEN_ODD:



Android开发之Path详解 安卓path_移动_13


isInverseFillType

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

toggleInverseFillType

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

举个例子:

Path path = new Path();
        path.addCircle(300,200,100, Path.Direction.CW);
        path.addCircle(200,200,100, Path.Direction.CW);
        path.setFillType(Path.FillType.INVERSE_EVEN_ODD);
        path.toggleInverseFillType();
        canvas.drawPath(path, paint);

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



Android开发之Path详解 安卓path_移动_14