Path类路径:
一个人走过的不间断轨迹就是路径;
画直线:
构造函数:
void moveTo(float x1,float y1)
void lineTo(float x2,float y2)
void close()
参数:
(x1,y1) 是直线的起始点,既将直线路径的绘制点定在(x1,y1)位置;
(x2,y2) 是(x1,y1)的终点,也是下一次绘制直线的起始点; lineTo()函数可以一直使用
close() 如果连续画了几条直线,但没有形成闭环,那么调用close()函数会将路径的首尾点连接起来,形成闭合;
三角形示例:
Paint paint = new Paint();
paint.setColor(Color.RED); //设置画笔颜色
paint.setStyle(Paint.Style.FILL);//填充样式改为描边
paint.setStrokeWidth(5);//设置画笔宽度
Path path = new Path();
path.moveTo(10, 10); //设定路径的起始点(只是起始位置,无任何轨迹)
path.lineTo(10, 100);//画第一条起始点的终点,也是第二条直线的起始点
path.lineTo(300, 100);//画第二条直线
path.close();//闭环
canvas.drawPath(path, paint);
未闭环效果图:
闭环效果图:
画弧线:
构造函数:
void arcTo(RectF oval,float startAngle,float sweepAngle)
void arcTo(float left,float top,float right,float bottom,float startAngle,float sweepAngle,boolean forceMoveTo)
void arcTo(RectF oval,float startAngle,float sweepAngle,boolean forceMoveTo)
参数:
oval: 生成椭圆的矩形工具类
startAngle: 弧开始的角度,已X轴正方向为0°
sweepAngle: 弧持续的角度
(left,top,right,bottom): 左上右下矩形
forceMoveTo: 是否强制将弧的起始点作为新的绘制起始点
示例1:
Paint paint = new Paint();
paint.setColor(Color.RED); //设置画笔颜色
paint.setStyle(Paint.Style.STROKE);//填充样式改为描边
paint.setStrokeWidth(5);//设置画笔宽度
Path path=new Path();
//把x=10,y=10 定位成起始绘制
path.moveTo(10,10);
RectF rectF=new RectF(100,10,200,100);
//设置路径为画弧线
path.arcTo(rectF,0,90);
//开始画轨迹
canvas.drawPath(path,paint);
结果图:
从图中可以看出,默认情况下路径是连贯的,由于我们在画弧前,因为提前定义好了起始位置,所以从起始位置转到RectF时的过程(斜线)也被画出来
这个时候只要把forceMoveTo参数设置为true即可,把上面示例代码更改为:
path.arcTo(rectF,0,90);替换为path.arcTo(rectF,0,90,true);
结果图:
添加系列函数:
跳过路径连贯性,直接在指定视图区域绘制路径
但是添加后的绘制结束位置,将是新的起始位置,后续不再调用addXXX系列函数,还是会连贯画出路径;
添加弧形:
跳过路径连贯性,直接在指定视图区域绘制矩形路径
构造函数:
void addArc(float left,float top,float right,float bottom,float startAngle,float sweepAngle)
void addArc(RectF oval, float startAngle, float sweepAngle)
参数:
(left,top,right,bottom): 左上右下矩形坐标
oval: 生成椭圆的矩形工具类
startAngle: 弧开始的角度,已X轴正方向为0°
sweepAngle: 弧持续的角度
示例:
Paint paint = new Paint();
paint.setColor(Color.RED); //设置画笔颜色
paint.setStyle(Paint.Style.STROKE);//填充样式改为描边
paint.setStrokeWidth(5);//设置画笔宽度
Path path=new Path();
//把x=10,y=10 定位成起始绘制
path.moveTo(10,10);
path.lineTo(100,50);
RectF rectF=new RectF(100,100,150,150);
//路径为弧线
path.addArc(rectF,0,90);
//开始画轨迹
canvas.drawPath(path,paint);
结果图:
从上图可以看出,我们先绘制了从(10,10)到(100,50)的线段,但是我们往路径中直接添加了一条弧线,弧线并没有与线段有连接,但是添加后的绘制结束位置,将是新的起始位置,后续不再调用addArc,还是会连贯画出路径
添加矩形:
构造函数:
void addRect(float left,float top,float right,float bottom,Path.Direction dir)
void addRect(RectF rect,Path.Direction dir)
参数:
(left,top,right,bottom): 左上右下矩形坐标
rect: 矩形工具类
dir参数有两个值:
Path.Direction.CCW: 代表顺时针方向绘制矩形路径;
Path.Direction.CW: 代表逆时针方向绘制矩形路径;
顺时针与逆时针:
顺时针为从右边开始为起始点,往左边绘制,逆时针为从左边开始为起始点,往右边绘制;
示例:
//第一个逆向生成
Paint paint = new Paint();
paint.setColor(Color.RED); //设置画笔颜色
paint.setStyle(Paint.Style.STROKE);//填充样式改为描边
paint.setStrokeWidth(5);//设置画笔宽度
Path CCWRectpath = new Path();
RectF rect1 = new RectF(50, 50, 240, 200);
//在这个区域逆时针画矩形路径
CCWRectpath.addRect(rect1, Path.Direction.CCW);
//第二个顺向生成
Path CWRectpath = new Path();
RectF rect2 = new RectF(290, 50, 480, 200);
//在这个区域顺时针画矩形路径
CWRectpath.addRect(rect2, Path.Direction.CW);
//先画出这两个路径
canvas.drawPath(CCWRectpath, paint);
canvas.drawPath(CWRectpath, paint);
效果如图:
第一个图是逆时针,第二个图是顺时针,由于画的位置不一样,所以导致两个图的位置不一样,跟顺时针逆时针没有关系,在四边形的矩形图里,我们看不出顺时针与逆时针的差别,顺时针与逆时针的差别仅仅是起始方向绘制点不同而已,在文字排版会比较明显;
添加圆角矩形:
构造函数:
void addRoundRect(RectF rect,float[] radii,Path.Direction dir)
void addRoundRect(RectF rect,float rx,float ry, Path.Direction dir)
参数:
rect: 矩形工具类
radii: 必须传入8个数值,分4租,分别对应每个角所使用的横纵轴半径如(10,15,20,25,30,35,40,45)其中10,15对应左上角,其它类推
dir参数有两个值:
Path.Direction.CCW: 代表顺时针方向绘制矩形路径;
Path.Direction.CW: 代表逆时针方向绘制矩形路径;
rx: 生成圆角统一的横轴半径
ry: 生成圆角统一的纵轴半径
顺时针与逆时针:
顺时针为从右边开始为起始点,往左边绘制,逆时针为从左边开始为起始点,往右边绘制;
示例:
Paint paint = new Paint();
paint.setColor(Color.RED); //设置画笔颜色
paint.setStyle(Paint.Style.STROKE);//填充样式改为描边
paint.setStrokeWidth(1);//设置画笔宽度
Path path = new Path();
RectF rect1 = new RectF(50, 50, 240, 200);
//统一横纵圆角半径
path.addRoundRect(rect1, 30, 30 , Path.Direction.CCW);
//四个角不同的圆角半径
RectF rect2 = new RectF(290, 50, 480, 200);
float radii[] ={10,15,20,25,30,35,40,45};
path.addRoundRect(rect2, radii, Path.Direction.CCW);
canvas.drawPath(path, paint);
效果如图:
第一个图为统一圆角半径,第二个图为不同的圆角半径;
添加圆形:
构造函数:
void addCircle(float x,float y,float radius,Path.Direction dir)
参数:
x: 圆心X轴坐标
y: 圆心Y轴坐标
radius: 园半径
dir参数有两个值:
Path.Direction.CCW: 代表顺时针方向绘制矩形路径;
Path.Direction.CW: 代表逆时针方向绘制矩形路径;
顺时针与逆时针:
顺时针为从右边开始为起始点,往左边绘制,逆时针为从左边开始为起始点,往右边绘制;
示例:
Paint paint = new Paint();
paint.setColor(Color.RED); //设置画笔颜色
paint.setStyle(Paint.Style.STROKE);//填充样式改为描边
paint.setStrokeWidth(1);//设置画笔宽度
Path path = new Path();
path.addCircle(100, 100, 50, Path.Direction.CCW);
canvas.drawPath(path, paint);
效果图:
添加椭圆:
构造函数:
void addOval(RectF oval,Path.Direction dir)
参数:
oval: 矩形工具类
dir参数有两个值:
Path.Direction.CCW: 代表顺时针方向绘制矩形路径;
Path.Direction.CW: 代表逆时针方向绘制矩形路径;
顺时针与逆时针:
顺时针为从右边开始为起始点,往左边绘制,逆时针为从左边开始为起始点,往右边绘制;
示例:
Paint paint = new Paint();
paint.setColor(Color.RED); //设置画笔颜色
paint.setStyle(Paint.Style.STROKE);//填充样式改为描边
paint.setStrokeWidth(1);//设置画笔宽度
Path path = new Path();
//矩形工具类
RectF rect = new RectF(10, 10, 200, 100);
//路径里添加椭圆
path.addOval(rect, Path.Direction.CCW);
canvas.drawPath(path, paint);
效果如图:
填充模式:
path的填充模式,只是告诉Paint画笔在当前路径里应该要填充哪一部分区域,而path.setFillType()函数就是用来界定告诉Paint填充的区域在哪里;
画笔的描边不属于填充,画笔设置描边的状态下,该函数设置不生效;
构造函数:
void setFillType(Path.FillType ft)
参数:
ft取值:
FillType.WINDING: 默认值,在当前路径范围里,有图形的内部区域填充
FillType.EVENT_ODD: 在图形与图形之间相交的区域不填充,路径内没有图形的区域也不填充(不填充区域,取默认背景色)
FillType.INVERSE_WINDING: 取反,在当前路径范围里,没有图形的区域去填充
FillType.INVERSE_EVEN_ODD: 取反,在在当前路径范围,图形与图形之间相交的区域填充,路径内没有图形的区域也填充
示例:
Paint paint =new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
Path path =new Path();
path.addRect(100,100,300,300,Path.Direction.CW);
path.addCircle(300,300,100,Path.Direction.CW);
path.setFillType(Path.FillType.WINDING);
canvas.drawPath(path,paint);
Paint设置描边图:
Paint设置为描边以后,无论Path.FillType取哪个值,都会和上图一样不做改变;
把paint.setStyle(Paint.Style.STROKE);改为paint.setStyle(Paint.Style.FILL);
Path.FillType.WINDING图:
FillType.EVENT_ODD图:
FillType.INVERSE_WINDING图:
FillType.INVERSE_EVEN_ODD图:
重置路径:
当我们需要重绘一条全新的路径时,Android开发人员为了重复利用空间,允许我们重置路径对象。路径对象一旦被重置,其中保存的所有路径都将被清空,这样我们就不需要重新定义一个路径对象了。重新定义路径对象的问题在于老对象的回收和新对象的内存分配,当然这些过程都是会消耗手机性能的。
构造函数:
void reset() //会清除内存,但是会保留FillType[填充模式]
void rewind() //不会清除内存,但会清除FillType及所有的直线、曲线、点的数据等,但是会保留数据结构
这两个函数的共同点是都会清空内部所保存的所有路径,但二者也有区别;
rewind()函数会清除FillType及所有的直线、曲线、点的数据等,但是会保留数据结构,这样可以实现快速重用,提高一定的性能。例如,重复绘制一类线段,它们的点的数量都相等,那么使用rewind()函数可以保留装在点数据的数据结构,效率会更高,但是一定要注意的是,只有在重复绘制相同的路径时,这些数据结构才是可以服用的。
reset()函数类似于新建一个路径对象,它的所有数据空间都会被回收并重新分配,但唯独不会清除FillType[填充模式]
示例:
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL);
Path path = new Path();
path.setFillType(Path.FillType.INVERSE_WINDING);
path.reset();
path.addCircle(100, 100, 50, Path.Direction.CW);
canvas.drawPath(path, paint);
效果图:
把上面的path.reset();改为path.rewind();
效果图: