自定义View(三)Canvas 图形绘制
之前的内容都是一些基础理论知识,还不能上手自定义View。下面进入实用工具系列 Canvas
Canvas 常用操作速查表
操作类型 | 相关API | 备注 |
---|---|---|
绘制颜色 | drawColor, drawRGB, drawARGB | 使用单一颜色填充整个画布 |
绘制基本形状 | drawPoint, drawPoints, drawLine, drawLines, drawRect, drawRoundRect, drawOval, drawCircle, drawArc | 依次为 点、线、矩形、圆角矩形、椭圆、圆、圆弧 |
绘制图片 | drawBitmap, drawPicture | 绘制位图和图片 |
绘制文本 | drawText, drawPosText, drawTextOnPath | 依次为 绘制文字、绘制文字时指定每个文字位置、根据路径绘制文字 |
绘制路径 | drawPath | 绘制路径,绘制贝塞尔曲线时也需要用到该函数 |
顶点操作 | drawVertices, drawBitmapMesh | 通过对顶点操作可以使图像形变,drawVertices直接对画布作用、 drawBitmapMesh只对绘制的Bitmap作用 |
画布剪裁 | clipPath, clipRect | 设置画布的显示区域 |
画布快照 | save, restore, saveLayerXxx, restoreToCount, getSaveCount | 依次为 保存当前状态、 回滚到上一次保存的状态、 保存图层状态、 回滚到指定状态、 获取保存次数 |
画布变换 | translate, scale, rotate, skew | 依次为 位移、缩放、 旋转、错切 |
Matrix(矩阵) | getMatrix, setMatrix, concat | 实际上画布的位移,缩放等操作的都是图像矩阵Matrix, 只不过Matrix比较难以理解和使用,故封装了一些常用的方法。 |
Canvas 绘制图形
简单的绘制图形这里直接就省略了,详情请跳转GcsSloop 安卓自定义View进阶-Canvas之绘制图形,我挑一些不太容易理解的,或者重要的讲一下。其实大神讲的都很清楚,我只是加深一下印象。
1.绘制点(drawPoint):
绘制一个点需要两个数值 X,Y
drawPoint()有两个重载的方法,
分别是三个参数 作用是绘制一个点
drawPoint(int,int,Paint)
两个参数 作用是绘制一组点,其中第一个参数Float[]是一组点坐标的数组
drawPoint(Float[],Paint)
canvas.drawPoint(200, 200, mPaint); //在坐标(200,200)位置绘制一个点 坐标分别是x,y
canvas.drawPoints(new float[]{ //绘制一组点,坐标位置由float数组指定
500,500,
500,600,
500,700
},mPaint);
2.绘制直线(drawLine)
绘制直线的方法drawLine()
也有两个重载的方法,用法和绘制点是一样的,只不过绘制一个直线需要四个数值,起始点的坐标(x1,y1)和终结点的坐标(x2,y2)。
canvas.drawLine(300,300,500,600,mPaint); // 在坐标(300,300)(500,600)之间绘制一条直线
canvas.drawLines(new float[]{ // 绘制一组线 每四数字(两个点的坐标)确定一条线
100,200,200,200,
100,300,200,300
},mPaint);
3.绘制矩形(drawRect)
绘制矩形有三个重载的方法。讲解绘制矩形首先要将一下Rect和RectF这两个类。
Rect和RectF
Rect和RectF两个类都是用来封装矩形的,其构造方法都有四个参数,分别是一个矩形左上角和右下角的坐标值。Rect和RectF的主要区别就是精度不同,Rect是int(整形)的,而RectF是float(单精度浮点型)的。
好了,讲了Rect之后绘制矩形就简单了;
// 第一种
canvas.drawRect(100,100,800,400,mPaint);
// 第二种
Rect rect = new Rect(100,100,800,400);
canvas.drawRect(rect,mPaint);
// 第三种
RectF rectF = new RectF(100,100,800,400);
canvas.drawRect(rectF,mPaint);
4.绘制圆角矩形(drawRoundRect)
绘制圆角矩形有两个重载方法;
// 第一种
RectF rectF = new RectF(100,100,800,400);
canvas.drawRoundRect(rectF,30,30,mPaint);
// 第二种
canvas.drawRoundRect(100,100,800,400,30,30,mPaint);
主要使用第一种。
我们看到绘制圆角矩形比绘制矩形多出了两个参数。
绘制圆角矩形中的圆角是椭圆意义上的圆角,不是圆的圆角。(其实椭圆包含圆)所以比绘制矩形多处的两个数值是椭圆的两个半径。这个需要用图表示一下。
圆角矩形
那么就出现了一个问题,万一rx和ry很大怎么办?大于矩形的边长怎么办?这个drawRoundRect()方法内部做了限制,如果rx和ry数值过大,那么就限制气等于相应边长的一半。
比如上边例子中的矩形边长分别是700和300,如果我将rx设置成800,ry设置成400,绘制的结果就是一个椭圆,两个半径分别是700/2,300/2。
例子:
// 矩形
RectF rectF = new RectF(100,100,800,400);
// 绘制背景矩形
mPaint.setColor(Color.GRAY);
canvas.drawRect(rectF,mPaint);
// 绘制圆角矩形
mPaint.setColor(Color.BLUE);
//其实在绘制的时候,rx和ry分别是等于350,150
canvas.drawRoundRect(rectF,700,400,mPaint);
半径过大的实例
5.绘制椭圆(drawOval)
绘制椭圆有两个重载的方法,一般用第一种
// 第一种
RectF rectF = new RectF(100,100,800,400);
canvas.drawOval(rectF,mPaint);
// 第二种
canvas.drawOval(100,100,800,400,mPaint);
如果传入的是长宽相等的矩形,那么绘制出来的就是一个圆。
6.绘制圆(drawCircle)
一个构造方法,其中的三个数值分别是圆心坐标,半径。
canvas.drawCircle(500,500,400,mPaint); // 绘制一个圆心坐标在(500,500),半径为400 的圆。
7.绘制圆弧(drawArc)
先看绘制圆弧的方法
// 第一种
public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint){}
// 第二种
public void drawArc(float left, float top, float right, float bottom, float startAngle,
float sweepAngle, boolean useCenter, @NonNull Paint paint) {}
圆弧的绘制其实相当于在椭圆的基础上切割出来一部分,那么怎么切割呢?
我们需要三个参数进行就能从椭圆(包含圆)上切割出圆弧:起始角度(startAngle),扫过的角度(sweepAngle),是否需要圆心(useCenter )
前边两个参数很好理解,第三个是怎么回事呢?下边分别是不需要圆心,和需要圆心
RectF rectF = new RectF(100,100,800,400);
// 绘制背景矩形
mPaint.setColor(Color.GRAY);
canvas.drawRect(rectF,mPaint);
// 绘制圆弧
mPaint.setColor(Color.BLUE);
canvas.drawArc(rectF,0,90,false,mPaint);
//-------------------------------------
RectF rectF2 = new RectF(100,600,800,900);
// 绘制背景矩形
mPaint.setColor(Color.GRAY);
canvas.drawRect(rectF2,mPaint);
// 绘制圆弧
mPaint.setColor(Color.BLUE);
canvas.drawArc(rectF2,0,90,true,mPaint);
结果
可以看到需要圆心绘制出来的就是一个扇形,不需要圆心绘制出来的就是连接起始点和终结点的加上圆弧的图形,类似于一个小船。