自定义 View 之 路径(Path)

这篇博文主要说一下自定义 View 中的路径。

在上一篇博文当中,可以画一些简单的图形了,但是学会了路径,就可以画一些较为复杂的图像了。

Android 提供了 drawPath(Path path, Paint paint) 这个方法来通过路径绘制图像。其参数 Path 就是今天的主要内容。

Path 封装了由直线、二次曲线和三次曲线组成的复合(多轮廓)几何路径。我们可以调用 canvas.drawPath 方法来绘制图形,也可以将文本绘制在路径上,也可以按照路径裁剪图形。

基本上 Path 可以分为几大类:

addXXX

  • addCircle(float x, float y, float radius, Path.Direction dir):向路径中添加一个圆。参数说明:

    • float x:圆心 X 坐标
    • float y:圆心 Y 坐标
    • float radius:圆半径
    • Path.Direction dir:绘制圆的方向,分顺时针还是逆时针,当组合图形时候才会有用,这里暂时放下。
  • addOval(RectF oval, Path.Direction dir):向路径中添加一个椭圆。
  • addOval(float left, float top, float right, float bottom, Path.Direction dir):向路径中添加一个椭圆。
  • addRect(RectF rect, Path.Direction dir):向路径中添加一个矩形。
  • addRect(float left, float top, float right, float bottom, Path.Direction dir):向路径中添加一个矩形。
  • addRoundRect(RectF rect, float rx, float ry, Path.Direction dir):向路径中添加一个圆角矩形。
  • addRoundRect(float left, float top, float right, float bottom, float rx, float ry, Path.Direction dir):向路径中添加一个圆角矩形。
  • addRoundRect(RectF rect, float[] radii, Path.Direction dir):向路径中添加一个圆角矩形。
  • addRoundRect(float left, float top, float right, float bottom, float[] radii, Path.Direction dir):向路径中添加一个圆角矩形。
  • addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle):向路径中添加一个弧形。
  • addArc(RectF oval, float startAngle, float sweepAngle):向路径中添加一个弧形。
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        paint.setColor(Color.GRAY);

        Path path = new Path();
        path.addCircle(300, 300, 200, Path.Direction.CW);
        path.addOval(50, 600, 550, 800, Path.Direction.CW);
        path.addRect(100, 900, 500, 1300, Path.Direction.CW);
        path.addRoundRect(new RectF(100, 1400, 500, 1800), 50, 20, Path.Direction.CW);
        path.addArc(100, 1900, 500, 2300, 180, 100);
        canvas.drawPath(path, paint);
    }

显示如下:

XXXTo

添加一条线到指定点:

  • lineTo(float x, float y):从路径终点添加一条直线到 (x,y),如果路径为空,则默认 (0,0)。
  • rLineTo(float dx, float dy):从路径上最后一个点添加一条直线到 (x,y),如果该点不存在,则为 (0,0)

将一条圆弧添加到路径:

  • arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
  • arcTo(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo)
  • arcTo(RectF oval, float startAngle, float sweepAngle)

如果路径为空,则以圆弧起点为起点(相当于多了一个 lineTo)

boolean forceMoveTo:该参数作用是路径的原终点和该圆弧起点是否相连,为 true 时候,圆弧起点和原终点不连接;为 false 时,圆弧起点和原终点相连接。

将一条二次贝塞尔曲线添加到路径:

  • quadTo(float x1, float y1, float x2, float y2)
  • rQuadTo(float dx1, float dy1, float dx2, float dy2)

将一条三次贝塞尔曲线添加到路径:

  • cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
  • rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3)

关于贝塞尔曲线,可以看这里:贝塞尔曲线扫盲

设置轮廓的起始点:

  • moveTo(float x, float y)
  • rMoveTo(float dx, float dy)

关闭当前路径:

  • close()

之前说过,路径可以理解为是你画笔在画布上画过的痕迹,在这个你可以顺着这个痕迹去添加文本啦之类的。

既然是痕迹,自然也就有起点和终点,也就是你画布落下和抬起的那两个点。

既然知道了起点和终点,那么 XXXTo 和 rXXXTo 就很好理解了。

一般的 XXXTo 都是以默认起点为起点,这个默认起点通过 moveTo(float x, float y) 方法来设置,如果没有设置起点,则默认 (0, 0)

而 rXXXTo 则以已有路径的终点作为起点,如果当前路径为空,自然也就没有终点了,也就以 (0, 0) 为起点;

arcTo 和其他不同,它的默认起点就是该圆弧的起点,也就是说会默认有一个 moveTo(x, y) 到该圆弧中设置的起点。

close() 的作用是将路径闭合,从当前路径的终点连接一条直线到该路径起点。