Path

自定义View-第七步:Path基础

2017-01-18  本文已影响77人  crossroads

前言

根据Gcssloop所学习的自定义View整理与笔记。

请关闭硬件加速,以免引起不必要的问题!
在AndroidMenifest文件中application节点下添上 android:hardwareAccelerated=”false”以关闭整个应用的硬件加速。

一、Path的常用方法【look一下,后续会详解的O(∩_∩)O~】

|作用|相关方法|备注|
|------|-----|----|
|移动起点|moveTo|移动下一次操作的起点位置|
|设置终点|setLastPoint|重置当前Path中最后一个点位置,如果在绘制之前调用,效果和moveTo相同|
|连接直线|lineTo|添加上一个点到当前点的直线到path|
|闭合路径|close|连接第一个点到最后一个点,形成一个闭合区域|
|添加内容|addRect,addRoundRect,addOval,addCircle,addPath,addArc,arcTo|添加(矩形,圆角矩形,椭圆,圆,路径,圆弧)到当前path|
|是否为空|isEmpty|判断path是否为空|
|是否为矩形|isRect|判断path是否是一个矩形|
|替换路径|set|用新的路径替换到当前路径所有内容|
|偏移路径|offset|对当前路径之前的操作进行偏移(不会影响之后的操作)|
|贝塞尔曲线|quadTo,cubicTo|分别为二次和三次贝塞尔曲线的方法|
|rXxx方法|rMoveTo, rLineTo, rQuadTo, rCubicTo|不带r的方法是基于原点的坐标系(偏移量),rXxx方法是基于当前点坐标系(偏移量),即以path最后的那个点|
|填充模式|setFillType, getFillType, isInverseFillType, toggleInverseFillType|设置,获取,判断和切换填充模式|
|提示方法|incReserve|提示path还有多少个点等待加入(可能会让path优化存储结构)|
|布尔操作【api19】|op|对两个path进行布尔运算,【即取交集,并集等操作】|
|计算边界|computeBounds|计算Path的边界|
|重置路径|reset,rewind|清除path中的内容【reset不保留内部数据结构,但会保留FillType,rewind会保留内部的数据结构,但不保留FillType】【FillType影响的是显示效果,数据结构影响重建速度】
|矩阵操作|transform|矩阵变换|

二、Path详解

看着多,其实就一点点,敲敲代码,瞬间理解,真的

1. lineTo

paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStrokeWidth(10);
paint.setStyle(Paint.Style.STROKE);
canvas.translate(300,300);
Path path = new Path(); 
path.lineTo(200, 200); 
path.lineTo(200,0);
canvas.drawPath(path, paint); // 绘制Path

效果图:


lineTo效果图

2.moveTo与setLastPoint


// moveTo,移动下一次操作的起点位置,不影响之前的操作,只影响之后的操作
public void moveTo (float x, float y)
// setLastPoint,设置之前操作的最后一个点的位置,影响之前和之后的操作
public void setLastPoint (float dx, float dy)

demo [moveTo]:

       canvas.translate(200, 200);
        Path path = new Path();
        path.lineTo(200, 200);
        path.moveTo(200,100);
        path.lineTo(200, 0);
        canvas.drawPath(path, paint);
moveTo效果图

demo [setLastPoint]:

        canvas.translate(200, 200);
        Path path = new Path();
        path.lineTo(200, 200);
        path.setLastPoint(200,100);
        path.lineTo(200, 0);
        canvas.drawPath(path, paint);
setLastPoint效果图

3. rLineTo与lineTo方法

       canvas.translate(100, 100);
        Path path = new Path();
//lineTo
        path.lineTo(200, 200);
        path.lineTo(200, 100);
//rLineTo
        path.rLineTo(200, 100);
      //  path.lineTo(0, 0);①
        canvas.drawPath(path, paint);
lineTo与rLineTo效果图.png
注释
translate将坐标移动到屏幕(100,100)的位置,也就是图上标注坐标原点的部分,那么lineto将均以该坐标为坐标原点rlineto执行前的点为(200,100),此时,会以(200,100)为坐标原点,即下一个点的实际位置为(400,200),当然,实际坐标的位置是不会改变的,如果在①执行的话,会发现添加了从(400,200)到(0,0)[即图上标注坐标原点] 的直线。
也就是说,lineTo和rLineTo的参考坐标不一样。
请原谅我叙述的本领,如果不清楚的话,就自己写个demo试试吧O(∩_∩)O~

4.close方法
用于连接当前最后一个点和最初的一个点(如果两个点不重合的话),最终形成一个封闭的图形,如果连接了最后一个点和第一个点仍然无法形成封闭图形,则close什么也不做

        canvas.translate(100, 100);
        Path path = new Path();
        path.lineTo(200, 200);
        path.lineTo(200, 0);
        path.close();
        canvas.drawPath(path, paint);
close效果图

实体三角形这样画

       paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.GREEN);
        Path path = new Path();
        path.moveTo(80, 200);// 此点为多边形的起点
        path.lineTo(120, 250);
        path.lineTo(80, 250);
        path.close(); // 使这些点构成封闭的多边形
        canvas.drawPath(path, paint);
三角形

5.addXxx与arcTo,注意区分addArc与arcTo

** 1. 基本图形**

// 圆形
public void addCircle (float x, float y, float radius, Path.Direction dir)
// 椭圆
public void addOval (RectF oval, Path.Direction dir)
// 矩形
public void addRect (float left, float top, float right, float bottom, Path.Direction dir)
public void addRect (RectF rect, Path.Direction dir)
// 圆角矩形
public void addRoundRect (RectF rect, float[] radii, Path.Direction dir)
public void addRoundRect (RectF rect, float rx, float ry, Path.Direction dir)
        canvas.translate(250, 250);
        Path path = new Path();
        //得到一个矩形,顺时针绘制矩形,左下角为最后一个点,获得①
        path.addRect(-100,-100,200,200, Path.Direction.CW);
        canvas.drawPath(path,paint);
        //重置最有后一个点的位置,获得②
        path.setLastPoint(-150,250);
        canvas.drawPath(path, paint);
        //得到一个矩形,获得③
        path.addRect(-160,-160,260,260,Path.Direction.CW);
        canvas.drawPath(path, paint);
效果图.png

这个时候把③注释,

     canvas.translate(250, 250);
        Path path = new Path();
        //得到一个矩形①
        path.addRect(-100,-100,200,200, Path.Direction.CW);
       // canvas.drawPath(path,paint);
        //重置最后一个点的位置②
        path.setLastPoint(-150,250);
        canvas.drawPath(path, paint);
        //得到一个矩形③
       //  path.addRect(-160,-160,260,260,Path.Direction.CW);
      // canvas.drawPath(path, paint);

则得到如下效果:


内心崩溃.jpg

为啥缺了一角?哈哈,因为没关闭硬件加速,记得关闭硬件加速哦,效果就是这样子的啦:

完美.jpg

ccw demo:

        canvas.translate(250, 250);
        Path path = new Path();
        //得到一个逆时针绘制的矩形,右上角为最后的一个点①
        path.addRect(-100,-100,200,200, Path.Direction.CCW);
        //重置最后一个点的位置②
        path.setLastPoint(-150,250);
        canvas.drawPath(path, paint);
        //得到一个矩形③
        path.addRect(-160,-160,260,260,Path.Direction.CW);
        canvas.drawPath(path, paint);

为了显示隐藏的那一角,我们还将③执行哈:


ccw效果图

2. addPath:将两个Path合并成为一个

public void addPath (Path src)
//将src进行了位移之后再添加进当前path中
public void addPath (Path src, float dx, float dy)
//将src使用Matrix进行变换后再添加到当前path中,同样的,Matrix后续讲解
public void addPath (Path src, Matrix matrix)

demo:

       canvas.translate(250, 250);
        Path path = new Path();
        Path src = new Path();
        path.addRect(-100,-100,200,200, Path.Direction.CCW);
        path.setLastPoint(-150,250);
        src.addRect(-160,-160,260,260,Path.Direction.CW);
     //合并路径
        path.addPath(src);
    //绘制合并后的路径
        canvas.drawPath(path, paint);

效果图和ccw效果图是一样滴,看上面最后一张图⤴️~

3.addArc与arcTo:添加一个圆弧到path

// addArc
public void addArc (RectF oval, float startAngle, float sweepAngle)
// arcTo
public void arcTo (RectF oval, float startAngle, float sweepAngle)
public void arcTo (RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)

addArc与arcTo的区别:

  1. addArc:直接添加一个圆弧到path中
  2. arcTo:添加一个圆弧到path,如果圆弧的起点和路径上次最后一个坐标点不相同,就连接两个点
    不过->如果有forceMoveTo,还是要看forceMoveTo的取值的哦。
forceMoveTo 含义 等价方法
true 不连接最后一个点与圆弧起点,不补全路径 public void addArc (RectF oval, float startAngle, float sweepAngle)
false 连接最后一个点与圆弧起点,即补全路径 public void arcTo (RectF oval, float startAngle, float sweepAngle)

看下边demo了解一下区别⤵️
demo addArc (arcTo true):

        canvas.translate(250, 250);
        Path path = new Path();
        path.lineTo(100, 100);
        
        RectF rectF = new RectF(0, 0, 200, 200);
        canvas.drawRect(rectF, paint);
        
        path.addArc(rectF, 0, 230);
        //等价于下边的作用
        // path.arcTo(rectF,0,230,true);
        canvas.drawPath(path, paint);
addArc效果图

demo arcTo (arcTo false):

   canvas.translate(250, 250);
        Path path = new Path();
        path.lineTo(100, 100);

        RectF rectF = new RectF(0, 0, 200, 200);
        canvas.drawRect(rectF, paint);

        path.arcTo(rectF, 0, 230);
        //等价于下边的作用
        //path.arcTo(rectF, 0, 230, false);
        canvas.drawPath(path, paint);
arcTo效果图

OK啦,这就是区别了,简单来说,就是是否自动补全路径。

4.isEmpty、 isRect、 set 和 offset

  1. isRect:
        Path path = new Path();
        Log.d("isEmpty1","isEmpty"+path.isEmpty());
        path.lineTo(100, 100);
        Log.d("isEmpty2","isEmpty"+path.isEmpty());
  /**
  *结果如下:
  * D/isEmpty1: isEmptytrue
  * D/isEmpty2: isEmptyfalse
  1. isRect:判断path是否是一个矩形,如果是一个矩形的话,会将矩形的信息存放进参数rect中。
       canvas.translate(50, 50);
        Path path = new Path();
        path.lineTo(0,400);
        path.lineTo(400,400);
        path.lineTo(400,0);
        path.lineTo(0,0);
        RectF rectF = new RectF();
        boolean rect = path.isRect(rectF);
        Log.d("isRect","isRect"+rect+"left:"+rectF.left);
/**
*结果是:
 *D/isRect: isRecttrueleft:0.0
**/
  1. set
       canvas.translate(160, 160);
        Path path = new Path(); 
        path.addRect(0, 0, 200, 200, Path.Direction.CW);

        Path src = new Path(); 
        src.addCircle(0, 0, 100, Path.Direction.CW);
        path.set(src); 
        canvas.drawPath(path, paint);
结果是一个圆
  1. offset:对path进行一段平移,只作用于当前的path
        public void offset (float dx, float dy)
        public void offset (float dx, float dy, Path dst)

补充

还记得上一节我们还没讲的方法么?根据路径绘制文字

public void drawTextOnPath (String text, Path path, float hOffset, float vOffset, Paint paint)
public void drawTextOnPath (char[] text, int index, int count, Path path, float hOffset, float vOffset, Paint paint)
        paint.setTextSize(24);
        paint.setColor(Color.BLUE);
        Path path = new Path();
        path.addArc(new RectF(0,0,100,100),10,209);
        canvas.drawTextOnPath("hello world hello world hello world ",path,0,0,paint);
效果图
上一篇 下一篇

猜你喜欢

热点阅读