Android自定义View之2D图形绘制(二)

在2D绘图中,Path路径绘制的功能无疑是最强大的,因为它不仅可以绘制任何形状的图形,还可以添加那些规则的图形,基本上图形绘制上的所有事情都可以做。那么接下来我们就具体说一说Path路径绘制的具体使用。

Path类的创建

创建Path类有两种方式
1、Path path = new Path() 无参构造函数
2、Path path = new Path(Path src) 通过另外一个Path实例来创建一个新的Path

Path的功能

Path添加线条

Path中有几个方法提供给我们去绘制线条
1、moveTo(float x, float y) 定义绘制的初始位置,绝对定位
2、rMoveTo(float x, float y) 定义绘制的初始位置,相对定位
3、lineTo(float x, float y) 将画笔移动到(x, y)的位置,并与上一个点之间绘制一条直线,绝对定位
4、rLineTo(float x, float y) 将画笔移动到(x, y)的位置,并与上一个点之间绘制一条直线,相对定位
5、close() 在第一个点和最后一个点之间绘制一条直线
下面我们通过两个例子来看一下具体的效果:

使用绝对定位

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Bitmap bitmap = Bitmap.createBitmap(1000, 1600, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
Path path = new Path();
path.moveTo(10,10);
path.lineTo(110, 10);
path.lineTo(110, 110);
path.lineTo(10, 110);
path.close();
canvas.drawPath(path, paint);
mImageView.setImageBitmap(bitmap);

效果图如下:
cmd-markdown-logo

使用相对定位

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Bitmap bitmap = Bitmap.createBitmap(1000, 1600, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
Path path = new Path();
path.moveTo(10,10);
path.rLineTo(100, 0);
path.rLineTo(0, 100);
path.rLineTo(-100, 0);
path.close();
canvas.drawPath(path, paint);
mImageView.setImageBitmap(bitmap);

效果图如下:
cmd-markdown-logo

总结

上面的两个例子分别用绝对定位和相对定位画出了两个大小、位置一样的正方形,证明两种定位方法都可以达到相同的目的,只不过是移动的距离需要做调整而已。

Path添加矩形、椭圆、扇形、弧线

添加矩形

1、addRect(RectF rect, Path.Direction dir) 直接添加一个RectF图形实例,dir为旋转方向(CW:顺时针, CCW:逆时针)
2、addRect(float left, float top, float right, float bottom, Path.Direction dir) 通过四条边的距离值添加
下面的代码会通过这两种方法绘制两个大小一样的正方形:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Bitmap bitmap = Bitmap.createBitmap(1000, 1600, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
Path path = new Path();
RectF rect = new RectF(10, 10, 210, 210);
path.addRect(rect, Path.Direction.CW);
path.addRect(320, 10, 520, 210, Path.Direction.CW);
canvas.drawPath(path, paint);
mImageView.setImageBitmap(bitmap);

效果图如下:
cmd-markdown-logo

添加圆角矩形

1、addRoundRect(RectF rect, float rx, float ry, Path.Direction dir) rx:X轴方向的圆角半径,ry:Y轴方向的圆角半径
2、addRoundRect(float left, float top, float right, float bottom, float rx, float ry, Path.Direction dir)
3、addRoundRect(RectF rect, float[] radii, Path.Direction dir) radii:该float类型的数组里面需要有8个值,分别表示矩形四个角的X轴和Y轴的圆角半径
4、addRoundRect(float left, float top, float right, float bottom, float[] radii, Path.Direction dir)
通过代码实现看一下效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Bitmap bitmap = Bitmap.createBitmap(1000, 1600, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
Path path = new Path();
RectF rect = new RectF(10, 10, 210, 210);
path.addRoundRect(rect, 10, 10, Path.Direction.CW);
path.addRoundRect(320, 10, 520, 210, 10, 10, Path.Direction.CW);
//圆角半径通过radii来定义
//path.addRoundRect(rect, new float[]{10, 10, 10, 10, 10, 10, 10, 10}, Path.Direction.CW);
//path.addRoundRect(320, 10, 520, 210, new float[]{10, 10, 10, 10, 10, 10, 10, 10}, Path.Direction.CW);
canvas.drawPath(path, paint);
mImageView.setImageBitmap(bitmap);

上面注释的代码和没有注释的代码最后的实现效果都是一样的,我们看一下绘制出来的图形
cmd-markdown-logo

添加椭圆

1、addOval(RectF oval, Path.Direction dir) 这两个方法的参数与添加矩形的参数含义一样
2、addOval(float left, float top, float right, float bottom, Path.Direction dir)
注意:如果oval为正方形,绘制出来的就是一个圆

接下来我们还是看一下代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Bitmap bitmap = Bitmap.createBitmap(1000, 1600, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
Path path = new Path();
RectF rect = new RectF(10, 10, 210, 410);
path.addOval(rect, Path.Direction.CW);
path.addOval(320, 10, 520, 410, Path.Direction.CW);
canvas.drawPath(path, paint);
mImageView.setImageBitmap(bitmap);

效果图如下:
cmd-markdown-logo

添加弧线

1、addArc(RectF oval, float startAngle, float sweepAngle) startAngle:开始的角度, sweepAngle:占用的角度
2、addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle)

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Bitmap bitmap = Bitmap.createBitmap(1000, 1600, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
Path path = new Path();
RectF rect = new RectF(10, 10, 210, 410);
path.addArc(rect, 10, 45);
path.addArc(320, 10, 520, 410, 10, 45);
canvas.drawPath(path, paint);
mImageView.setImageBitmap(bitmap);

效果图如下:
cmd-markdown-logo

Path添加曲线和贝塞尔曲线

除了弧线这种曲线图形,我们还可以利用贝塞尔曲线绘制出更加复杂的曲线图形
贝塞尔曲线的具体一些解释这里就不多说了,大家可以看一下这篇博客,个人觉得该博主讲解的很清楚了安卓自定义View进阶-Path之贝塞尔曲线

一阶贝塞尔曲线

其实一阶贝塞尔曲线就是一条直线,我们可以通过上一篇中普通直线的方式绘制就可以了

二阶贝塞尔曲线

二阶贝塞尔曲线总共有三个点来对曲线的形状进行控制,分别是:起点,终点和控制点
我们可以定义两个固定的点作为起点和终点,然后通过改变控制点来改变曲线的形状

下面我们来看一段绘制二姐贝塞尔曲线的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Bitmap bitmap = Bitmap.createBitmap(1080, 1600, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
Path path = new Path();
path.moveTo(10, 100);
path.quadTo(310, 400, 1010, 100); //二阶贝塞尔曲线
canvas.drawPath(path, paint);
mImageView.setImageBitmap(bitmap);

效果图如下:
cmd-markdown-logo

接来下我们不改变起点和终点的位置,只改变控制点的坐标位置,图形会发生变化:

1
2
3
......
path.quadTo(710, 400, 1010, 100); //二阶贝塞尔曲线
......

控制点改变后绘制的曲线:
cmd-markdown-logo

二阶贝塞尔曲线也有绝对定位和相对定位之分:
绝对定位:quadTo
相对定位:rQuadTo

三阶贝塞尔曲线

三阶贝塞尔曲线总共有四个点来对曲线的形状进行控制,分别是:起点,终点和两个控制点
三阶贝塞尔曲线可以画出比二阶贝塞尔曲线更加不规则的曲线图形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Bitmap bitmap = Bitmap.createBitmap(1080, 1600, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
Path path = new Path();
path.moveTo(10, 100);
path.cubicTo(210, 400, 800, 200,1010, 600);
canvas.drawPath(path, paint);
mImageView.setImageBitmap(bitmap);

效果图如下:
cmd-markdown-logo
三阶贝塞尔曲线与二阶的一样,有相对和绝对定位之分:
绝对定位:cubicTo
相对定位:rCubicTo

Path图形进行计算

Path图形计算我们可以简单的理解为两个图形部分重叠在一起的时候,我们需要选取的是那部分,在Path中总共有五种情况,我们可以通过下表看一下:

Path图形计算方式 说明(path1和path2代表两个图形)
DIFFERENCE path1去除与path2重叠部分的剩余图形
INTERSECT path1和path2的交集
REVERSE_DIFFERENCE 与DIFFERENCE相反,path2去除与path1重叠部分的剩余图形
UNION path1和path2的并集
XOR path1和path2的并集减掉path1和path2的交集

总结

以上就是一些常用的图形绘制的方法,了解这些方法的运用是后面学习自定义View的基础,在后面的文章中我们会进入实战环节,开始从一些简单的自定义View慢慢的深入到复杂的自定义View