Android 自定义控件:Path

在 Canvas 的学习中,只能画一些比较规则的图形,如方形,圆,弧线等。如果要画一些比较复杂的图形,只要计算好坐标,就需用到 Path 类就能做到,以及著名的贝塞尔曲线也是用 Path 来实现。这里列举下 Path 常用的方法。

画笔等相关设置为:

    private void init() {
        mPaint = new Paint();
        mPaint.setColor(Color.parseColor("#2d6fff"));
        mPaint.setStyle(Paint.Style.STROKE);  //设置画笔模式为描边
        mPaint.setStrokeWidth(10f);         //设置画笔宽度为10px
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPath = new Path();
    }

1. lineTo

voidlineTo(float x, float y)

Add a line from the last point to the specified point (x,y).

此方法传入的参数为点的 x,y 坐标,表示的上次画笔的位置到目标点的位置的连线。一开始画笔的位置为(0,0)。

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.parseColor("#dcdcdc"));
        mPath.lineTo(200,200);
        mPath.lineTo(200,0);
        canvas.drawPath(mPath,mPaint);
    }

从(0,0)到点(200,200),形成连线,这样画笔的位置就到了(200,200)。再次将画笔的位置移动到点(200,0),形成新的连线。

效果:

2. moveTo

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

voidmoveTo(float x, float y)

Set the beginning of the next contour to the point (x,y).

 

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.parseColor("#dcdcdc"));
        mPath.lineTo(200, 200);
        mPath.lineTo(200, 0);
        //经过这样的移动,起点位置为(200,0)
        //将起点移动到(200,200)
        mPath.moveTo(200, 200);
        //再次连线到点(400,0)
        mPath.lineTo(400, 0);
        canvas.drawPath(mPath, mPaint);
    }

效果:

3. close 

voidclose()

Close the current contour.

用于连接第一个点连接到最后一个点,形成一个闭合区域。

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.parseColor("#dcdcdc"));
        mPath.moveTo(200,200);
        mPath.lineTo(200,400);
        mPath.lineTo(400,400);
        canvas.drawPath(mPath, mPaint);
    }

未调用 close 时候的效果:

调用 close 方法后,形成闭合:

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.parseColor("#dcdcdc"));
        mPath.moveTo(200,200);
        mPath.lineTo(200,400);
        mPath.lineTo(400,400);
        mPath.close();
        canvas.drawPath(mPath, mPaint);
    }

 效果:

4.  addRect, addRoundRect, addOval, addCircle

此四个方法与 Canvas 中的方法类似,这里就只列举 addRect 的用法:

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.parseColor("#dcdcdc"));
        RectF rectF = new RectF(200,200,500,500);
        mPath.addRect(rectF, Path.Direction.CW);
        canvas.drawPath(mPath, mPaint);
    }

其中 Path.Direction 中存在两种:

Path.Direction.CW

Path.Direction.CCW

类型解释翻译
CWclockwise顺时针
CCWcounter-clockwise逆时针

这里是指在画图的时候按照顺时针或者逆时针的顺序进行画图。

5. addPath

用于将两个 Path 合并:

voidaddPath(Path src, Matrix matrix)

Add a copy of src to the path, transformed by matrix

voidaddPath(Path src)

Add a copy of src to the path

voidaddPath(Path src, float dx, float dy)

Add a copy of src to the path, offset by (dx,dy)

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.parseColor("#dcdcdc"));
        RectF rectF = new RectF(200, 200, 500, 500);
        mPath.addRect(rectF, Path.Direction.CW);
        mPathSecond.addCircle(200, 350, 150, Path.Direction.CCW);
        mPath.addPath(mPathSecond);
        canvas.drawPath(mPath, mPaint);
    }

效果:

6. addArc 和 arcTo

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

 addArc:

voidaddArc(float left, float top, float right, float bottom, float startAngle,float sweepAngle)

Add the specified arc to the path as a new contour.

voidaddArc(RectF oval, float startAngle, float sweepAngle)

Add the specified arc to the path as a new contour.

 arcTo:

voidarcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)

Append the specified arc to the path as a new contour.

voidarcTo(float left, float top, float right, float bottom, float startAngle,float sweepAngle, boolean forceMoveTo)

Append the specified arc to the path as a new contour.

voidarcTo(RectF oval, float startAngle, float sweepAngle)

Append the specified arc to the path as a new contour.

forceMoveTo 的作用:

forceMoveTo含义等价方法
true将最后一个点移动到圆弧起点,即不连接最后一个点与圆弧起点public void addArc (RectF oval, float startAngle, float sweepAngle)
false不移动,而是连接最后一个点与圆弧起点public void arcTo (RectF oval, float startAngle, float sweepAngle)

forceMoveTo 为 true 的时候:

forceMoveTo 为 false 的时候:

代码如下:

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.parseColor("#dcdcdc"));
        RectF oval = new RectF(200, 200, 500, 500);
        mPath.lineTo(100, 300);
        mPath.arcTo(oval, 0, 270, false);
        canvas.drawPath(mPath, mPaint);
    }

7. 二阶贝塞尔曲线

二阶曲线由两个数据点,一个控制点来描述曲线状态。二阶曲线对应的方法是 quadTo :

voidquadTo(float x1, float y1, float x2, float y2)

Add a quadratic bezier from the last point, approaching control point (x1,y1), and ending at (x2,y2).

其中,起点为 Path的起点,控制点为 x1,y1,终点为 x2,y2。

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.parseColor("#dcdcdc"));
        mPath.moveTo(100, 100);
        mPath.quadTo(200, 200, 500, 100);
        canvas.drawPath(mPath, mPaint);
    }

效果:

8. 三阶贝塞尔曲线

三阶曲线由两个数据点,两个控制点来描述曲线状态。三阶曲线对应的方法是 cubicTo

voidcubicTo(float x1, float y1, float x2, float y2, float x3, float y3)

Add a cubic bezier from the last point, approaching control points (x1,y1) and (x2,y2), and ending at (x3,y3).

其中,起点为 Path的起点,终点为 x3,y3,控制点为 x1,y1 和 x2,y2。

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.parseColor("#dcdcdc"));
        mPath.moveTo(100, 100);
        mPath.cubicTo(200, 500, 400, 300, 500, 100);
        canvas.drawPath(mPath, mPaint);
    }

效果:

参考:

https://www.gcssloop.com/customview/Path_Over

https://www.gcssloop.com/customview/Path_Basic/

https://www.gcssloop.com/customview/Path_Bezier

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值