美文网首页自定义viewAndroid知识Android开发
Android自定义控件(三 .0)Path的基本操作

Android自定义控件(三 .0)Path的基本操作

作者: Jackson杰 | 来源:发表于2017-04-14 17:01 被阅读74次

    前面http://www.jianshu.com/p/35765aa6f7d9 所讲的绘制的图形都是基本的简单图形,如矩形,员,圆弧等。如果对于一些复杂的图形(五角星,心形)的绘制,前面的绘图方法就无能为力了。而使用Path不仅可以绘制简单的图形,还能复制一些复杂的图形。
    Google官网上Path的链接为:https://developer.android.google.cn/reference/android/graphics/Path.html
    google官网上对path的解释为:

    • The Path class encapsulates compound (multiple contour) geometric paths consisting of straight line segments, quadratic curves, and cubic curves. It can be drawn with canvas.drawPath(path, paint), either filled or stroked (based on the paint's Style), or it can be used for clipping or to draw text on a path.
    • 大意是Path类封装了直线段,二次bezier曲线,三次bezier曲线等几何路径,可以通过canvas.drawPath(path, paint)方法画出,画笔的类型可以是filled 或者 stroked,可以用于通过路径裁剪或者绘制文本。
    Path的相关方法
    作用 相关方法 备注
    移动起点 [moveTo](https://developer.android.google.cn/reference/android/graphics/Path.html#moveTo(float, float))(float x, float y) Set the beginning of the next contour to the point (x,y).
    设置终点 [setLastPoint](https://developer.android.google.cn/reference/android/graphics/Path.html#setLastPoint(float, float))(float dx, float dy) Sets the last point of the path.
    连接直线 [lineTo](https://developer.android.google.cn/reference/android/graphics/Path.html#lineTo(float, float))(float x, float y) Add a line from the last point to the specified point (x,y).
    闭合路径 close() Close the current contour.
    添加内容 [addArc](https://developer.android.google.cn/reference/android/graphics/Path.html#addArc(float, float, float, float, float, float))、[addCircle](https://developer.android.google.cn/reference/android/graphics/Path.html#addCircle(float, float, float, android.graphics.Path.Direction))、[addOval](https://developer.android.google.cn/reference/android/graphics/Path.html#addOval(android.graphics.RectF, android.graphics.Path.Direction))、[addPath](https://developer.android.google.cn/reference/android/graphics/Path.html#addPath(android.graphics.Path, android.graphics.Matrix))、[addRect](https://developer.android.google.cn/reference/android/graphics/Path.html#addRect(android.graphics.RectF, android.graphics.Path.Direction))、[addRoundRect](https://developer.android.google.cn/reference/android/graphics/Path.html#addRoundRect(android.graphics.RectF, float, float, android.graphics.Path.Direction))、[arcTo](https://developer.android.google.cn/reference/android/graphics/Path.html#arcTo(android.graphics.RectF, float, float, boolean)) 添加( 圆弧、 圆, 椭圆,路径,矩形, 圆角矩形, ) 到当前Path
    是否为空 isEmpty() Returns true if the path is empty (contains no lines or curves)
    是否为矩形 isRect(RectF rect) Returns true if the path specifies a rectangle.
    替换路径 set(Path src) Replace the contents of this with the contents of src.
    偏移路径 [offset](https://developer.android.google.cn/reference/android/graphics/Path.html#offset(float, float)) Offset the path by (dx,dy)
    重置路径 reset()、rewind() Clear any lines and curves from the path, making it empty./Rewinds the path: clears any lines and curves from the path but keeps the internal data structure for faster reuse.
    rXxx方法 [rCubicTo](https://developer.android.google.cn/reference/android/graphics/Path.html#rCubicTo(float, float, float, float, float, float))、[rLineTo](https://developer.android.google.cn/reference/android/graphics/Path.html#rLineTo(float, float))、[rMoveTo](https://developer.android.google.cn/reference/android/graphics/Path.html#rMoveTo(float, float))、[rQuadTo](https://developer.android.google.cn/reference/android/graphics/Path.html#rQuadTo(float, float, float, float)) 不带r的方法是基于原点的坐标系(偏移量), rXxx方法是基于当前点坐标系(偏移量)
    贝塞尔曲线 [quadTo](https://developer.android.google.cn/reference/android/graphics/Path.html#quadTo(float, float, float, float))、[cubicT](https://developer.android.google.cn/reference/android/graphics/Path.html#cubicTo(float, float, float, float, float, float)) 分别为二次和三次贝塞尔曲线的方法
    矩阵操作 transform Transform the points in this path by matrix
    填充模式 setFillTypetoggleInverseFillType()、isInverseFillType()、getFillType() 设置、切换、判断和获取填充模式
    计算边界 [computeBounds](https://developer.android.google.cn/reference/android/graphics/Path.html#computeBounds(android.graphics.RectF, boolean)) Compute the bounds of the control points of the path, and write the answer into bounds.
    布尔操作 [op](https://developer.android.google.cn/reference/android/graphics/Path.html#op(android.graphics.Path, android.graphics.Path, android.graphics.Path.Op)) Set this path to the result of applying the Op to the two specified paths
    lineTo

    首先先要说的是lineTo ,lineTo的方法如下:
    [lineTo](https://developer.android.google.cn/reference/android/graphics/Path.html#lineTo(float, float))(float x, float y)
    Add a line from the last point to the specified point (x,y)
    在上次的结束点和指定的点之间添加一条line,the last point是上次操作结束的点,如果没有上次结束的点呢,额,那就默认为坐标原点。
    现在测试一下:

     int mWidth = getWidth();
    int mHeight = getHeight();
    canvas.translate(mWidth/2,mHeight/2);  //坐标移动到屏幕中心
    Path path=new Path();       //创建Path
    path.lineTo(200,200);
    path.lineTo(200,-200);
    canvas.drawPath(path,mPaint2);  //绘制Path
    
    Image.png

    在例子中,我们调用了两次lineTo,第一次调用时,因为之前没有调用过,所以默认点是坐标原点,第二次调用时,因为上次调用的结束点是(200,200),所以这次lineTo是(200,200)到(200,-200)之间的连线。

    moveTo 和 setLastPoint:

    [moveTo](https://developer.android.google.cn/reference/android/graphics/Path.html#moveTo(float, float))(float x, float y) :Set the beginning of the next contour to the point (x,y).
    [setLastPoint](https://developer.android.google.cn/reference/android/graphics/Path.html#setLastPoint(float, float))(float dx, float dy):Sets the last point of the path
    这两个方法看起来比较类似,其实是有很大不同的,如下表所示:

    方法名 | 简介 | 是否影响之前的操作 | 是否影响之后操作
    ------------|---------|--------------|--------------|------------
    [moveTo](https://developer.android.google.cn/reference/android/graphics/Path.html#moveTo(float, float))(float x, float y)|设置下次Path的起点|否|是
    [setLastPoint](https://developer.android.google.cn/reference/android/graphics/Path.html#setLastPoint(float, float))(float dx, float dy)|设置上次操作最后一个点的位置|是|是
    直接上代码:

    canvas.translate(mWidth / 2, mHeight / 2);
    Path path = new Path();
    path.lineTo(200,200);
    path.moveTo(200,0);
    path.lineTo(200,-200);
    canvas.drawPath(path,mPaint2);
    
    Image.png

    moveTo只改变下次操作的起点,在执行完第一次LineTo的时候,本来的默认点位置是(200,200),但是moveTo将其改变成为了(200,0),所以在第二次调用lineTo的时候就是连接(200,0) 到 (200,-200) 之间的直线。

    • 下面是setLastPoint
    canvas.translate(mWidth/2,mHeight/2);
    Path path=new Path();
     path.lineTo(200,200);
     canvas.drawPoint(200,200,mPaint2);
     path.setLastPoint(200,100);
     path.lineTo(200,-200);
     canvas.drawPath(path,mPaint2);
    

    setLastPoint是重置上一次操作的最后一个点,在执行完第一次的lineTo的时候,最后一个点是(200,200),而setLastPoint更改最后一个点为(200,100),所以在实际执行的时候,第一次的lineTo就不是从原点到(200,200)的连线了,而变成了从原点到C(200,100)之间的连线了。

    在执行完第一次lineTo和setLastPoint后,最后一个点的位置是(200,100),所以在第二次调用lineTo的时候就是(200,100) 到 (200,-200) 之间的连线。

    Image.png
    close

    close():Close the current contour
    close方法用于连接当前最后一个点和最初的一个点(如果两个点不重合的话),最终形成一个封闭的图形。

    canvas.translate(mWidth/2,mHeight/2);
    Path path=new Path();
    path.lineTo(200,200); path.lineTo(200,-200);
    path.close();
    canvas.drawPath(path,mPaint2);
    
    Image.png

    注意:close的作用是封闭路径,与连接当前最后一个点和第一个点并不等价。如果连接了最后一个点和第一个点仍然无法形成封闭图形,则close什么 也不做。

    addXXX和arcTo

    这次方法主要是在Path中添加基本图形,重点区分addArc与arcTo。

    类型 解释 说明
    CW clockwise 顺时针
    CCW counter-clockwise 逆时针
    addPath

    addPath(Path src) :Add a copy of src to the path
    [addPath](https://developer.android.google.cn/reference/android/graphics/Path.html#addPath(android.graphics.Path, float, float))(Path src, float dx, float dy):Add a copy of src to the path, offset by (dx,dy)
    [addPath](https://developer.android.google.cn/reference/android/graphics/Path.html#addPath(android.graphics.Path, android.graphics.Matrix))(Path src, Matrix matrix):Add a copy of src to the path, transformed by matrix
    addPath方法很明了,就是把两个Path合并为一个
    第二个方法是将src平移后再合并在一起
    第三个方法是将src进行Matrix变换后再合并到一起

     canvas.translate(mWidth/2,mHeight/2);
    Path path=new Path();
    Path src=new Path();
    path.addRect(-200,-200,200,200,Path.Direction.CW);
    src.addCircle(0,0,100,Path.Direction.CW);
    path.addPath(src,0,-200);
    canvas.drawPath(path,mPaint2);
    
    Image.png
    addArc与arcTo

    [addArc](https://developer.android.google.cn/reference/android/graphics/Path.html#addArc(android.graphics.RectF, float, float))(RectF oval, float startAngle, float sweepAngle)--- Add the specified arc to the path as a new contour.
    [addArc](https://developer.android.google.cn/reference/android/graphics/Path.html#addArc(float, float, float, float, float, float))(float left, float top, float right, float bottom, float startAngle, float sweepAngle)---Add the specified arc to the path as a new contour
    [arcTo](https://developer.android.google.cn/reference/android/graphics/Path.html#arcTo(android.graphics.RectF, float, float, boolean))(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)---Append the specified arc to the path as a new contour.
    [arcTo](https://developer.android.google.cn/reference/android/graphics/Path.html#arcTo(float, float, float, float, float, float, boolean))(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.
    [arcTo](https://developer.android.google.cn/reference/android/graphics/Path.html#arcTo(android.graphics.RectF, float, float, boolean))(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)---Append the specified arc to the path as a new contour

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

    另外,可以看到arcTo方法最后一个参数是个boolean类型的,forceMoveTo,有什么作用呢

    forceMoveTo 含义
    true 将最后一个点移动到圆弧起点,即不连接最后一个点与圆弧起点
    false 不移动,而是连接最后一个点与圆弧起点

    addArc

    canvas.translate(mWidth/2,mHeight/2);
    Path path=new Path();
    path.lineTo(100,100);
    RectF oval=new RectF(0,0,300,300);
    path.addArc(oval,0,270);
    canvas.drawPath(path,mPaint2);
    
    Paste_Image.png

    arcTo

    canvas.translate(mWidth/2,mHeight/2);
    Path path=new Path();
    path.lineTo(100,100);
    RectF oval=new RectF(0,0,300,300);
    path.arcTo(oval,0,270);
    canvas.drawPath(path,mPaint2);
    
    Paste_Image.png
    isEmpty、 isRect、isConvex、 set 和 offset
    dst状态 效果
    dst不为空 将当前path平移后的状态存入dst中,不会影响当前path
    dst为空(null) 平移将作用于当前path,相当于第一种方法
    canvas.translate(mWidth/2,mHeight/2);
    Path path=new Path();
    path.addCircle(0,0,100,Path.Direction.CW);
    Path dst=new Path();
     path.offset(300,0,dst);
    canvas.drawPath(path,mPaint2);
    path.offset(300,0);
    canvas.drawPath(path,mPaint2);
    
    Paste_Image.png
    代码下载地址
    https://github.com/baojie0327/ViewAndGroup

    相关文章

      网友评论

        本文标题:Android自定义控件(三 .0)Path的基本操作

        本文链接:https://www.haomeiwen.com/subject/oqopottx.html