绘制:简单来说也就是画画,就是把想展示的效果在页面中展示出来
1. 如何实现?
关键:绘制方法有几个,最常用的是重写onDraw()方法,负责主体内容绘制
定义类继承自View,重写onDraw方法,准备工作就绪,这里我们自定义一个画图类
public class CustomizePaint extends View {
...
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 这里写你的自定义绘制代码
...
}
...
}
2. 在哪里绘制什么?
刚刚好,就在我们重写的onDraw方法中提供给我们一个Canvas,直译:画布;很形象吧,我们的杰作就在这块画布上诞生。
画圆?画线?画字?画图片?别急,canvas不止是一个画布,它还为我们提供了一系列方便的模具,让我们可以快速上手实现一些简单图形的绘制。
先说一下坐标系:每个View都有自己的坐标系,view左上角为该坐标系的原点, 沿坐标原点向右为x轴正方向,向下为y轴正方向
canvas的官方api文档(科学上网哦):https://developer.android.com/reference/android/graphics/Canvas.html
可以直接看官方文档,以下是部分的api说明:
canvas的draw-xxx系列
API | 功能说明 | 备注(参数说明) |
---|---|---|
drawCircle(float cx, float cy, float radius, Paint paint) | 画圆 | 圆心坐标、半径 |
drawColor(long color, BlendMode mode) drawARGB(int a, int r, int g, int b) drawRGB(int r, int g, int b) | 区域上色 | mode参数为绘制模式,放在后面细讲 |
drawLine(float startX, float startY, float stopX, float stopY, Paint paint) | 画线 | 线条的起始点坐标 |
drawRect(float left, float top, float right, float bottom, Paint paint) | 画矩形 | 矩形四条边坐标 |
drawOval(float left, float top, float right, float bottom, Paint paint) | 画椭圆 | 想象你要绘制椭圆的外切矩形,参数为矩形的四条边坐标,只能绘制横着或竖着的圆,不能绘制斜的 |
drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint) | 画圆角矩形 | 相当于先画直角矩形,沿四个角画横纵向半径分别为rx,ry的椭圆形成的样子 |
drawPoint(float x, float y, Paint paint) | 画点 | |
drawPoints(float[] pts, int offset, int count, Paint paint) | 批量画点 | pts是绘制点组成的数组,数组中两两成一对坐标,offset是从第几个数开始绘制,count为绘制几个数字 |
drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, Paint paint) | 画弧形或扇形 | 前四个参数描述扇形所在的椭圆,然后是弧度的起始和划过的弧度,以x轴向右为0度位置,顺时针为正,逆时针为负角度,useCenter表示是否连接到圆心,连接为扇形,否则为弧形 |
drawPath(Path path, Paint paint) | 画任意路径 | 可定制性更高 |
drawText(String text, float x, float y, Paint paint) | 画字 | |
drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) | 画图片 |
drawPath额外说明:
Path可以描述直线,二次曲线,三次曲线,圆,椭圆,矩形,弧形等
Path的官方文档:https://developer.android.com/reference/android/graphics/Path
API | 说明 | 备注 |
add-xxx方法(主要是添加封闭图形) | ||
addCircle(float x, float y, float radius, Path.Direction dir) | 画封闭的圆 | dir:画圆的路径方向,顺时针(cw)和逆时针(ccw),只在需要填充图形且图形出现自相交时判断填充范围 |
addOval(RectF oval, Path.Direction dir) | 添加椭圆 | |
addRect(RectF rect, Path.Direction dir) | 添加矩形 | |
addRoundRect(RectF rect, float rx, float ry, Path.Direction dir) | 添加圆角矩形 | |
addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle) | 添加弧形 | addArc为使用了forceMoveTo为true的简化版arcTo xxxTo方法 |
arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo) | 画线,直线或曲线 | forceMoveto画弧形的过程中是否和之前的轨迹自动衔接,true为断开独立绘制,false为有线进行连接 |
cubicTo(float x1, float y1, float x2, float y2, float x3, float y3) | 画三次贝塞尔曲线 | |
lineTo(float x, float y) | 画目标点为(x,y)的直线 | |
moveTo(float x, float y) | 移动到(x,y)位置,并不画线 | |
quadTo(float x1, float y1, float x2, float y2) | 画二次贝塞尔曲线 | |
rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3) rLineTo(float dx, float dy) rMoveTo(float dx, float dy) rQuadTo(float dx1, float dy1, float dx2, float dy2) | r是relative的缩写,和没有r的方法区别在于起点位置,绝对位置的起点位置为(0,0),相对位置的起点为上一次path路径的终点 | |
close() 封闭当前图形 连接起点和终点 |
LineTo和rLineTo:
示例:
// 绘制背景颜色
canvas.drawColor(Color.parseColor("#E4BCB2"));
// 第一行第一个
canvas.drawCircle(100, 100, 50, strokePaint);
// 第一行第二个
canvas.drawRect(250, 50, 400, 150, strokePaint);
// 第一行第三个
canvas.drawRect(500, 50, 700, 150, strokePaint);
canvas.drawOval(500, 50, 700, 150, strokePaint);
// 第一行第四个
canvas.drawRoundRect(800, 50, 1000, 150, 30, 30, strokePaint);
canvas.drawCircle(830, 80, 30, strokePaint);
canvas.drawCircle(970, 80, 30, strokePaint);
canvas.drawCircle(830, 120, 30, strokePaint);
canvas.drawCircle(970, 120, 30, strokePaint);
// 画线
canvas.drawLine(0, 200, 1300, 200, strokePaint);
// 画点
pointPaint.setStrokeWidth(30); // 设置点的大小
pointPaint.setStrokeCap(Paint.Cap.ROUND); // 设置点的形状 BUTT或SQUARE为方形点,ROUND为圆形点
canvas.drawPoint(100, 250, pointPaint);
// 批量画点
pointPaint.setStrokeCap(Paint.Cap.SQUARE);
float[] points = {200, 250, 350, 250, 275, 350};
canvas.drawPoints(points, 0, 6, pointPaint);
// 绘制弧形
canvas.drawArc(500, 250, 600, 350, 0, -90, false, strokePaint);
// 绘制扇形 圆的1/4右上角
canvas.drawArc(800, 250, 900, 350, 0, -90, true, strokePaint);
canvas.drawLine(0, 400, 1300, 400, strokePaint);
canvas.drawCircle(465, 545, 40, strokePaint);
canvas.drawCircle(465, 545, 25, strokePaint);
canvas.drawCircle(635, 545, 40, strokePaint);
canvas.drawCircle(635, 545, 25, strokePaint);
canvas.drawCircle(550, 600, 101, strokePaint);
canvas.drawCircle(550, 600, 100, pinkPaint);
canvas.drawOval(490, 610, 610, 690, whitePaint);
blackPaint.setColor(Color.BLACK);
canvas.drawOval(520, 638, 580, 678, blackPaint);
float[] eyePoints = {520, 615, 580, 615};
pointPaint.setStrokeCap(Paint.Cap.ROUND);
pointPaint.setStrokeWidth(20);
canvas.drawPoints(eyePoints, 0, 4, pointPaint);
3. 拿什么绘制?
只有画布还不够,要呈现效果,我们还需要一支画笔,就是我们的Paint类,负责绘制的风格和样式。
paint的官方api地址(科学上网哦):https://developer.android.com/reference/android/graphics/Paint.html
基本样式设置:
API | 说明 | 备注 |
setStyle(Paint.Style style) | 设置风格是边框型还是填充型 | 枚举值:FILL、STROKE、FILL_AND_STROKE |
setStrokeWidth(float width) | 设置边框大小 | |
setColor(long color) setColor(int color) setARGB(int a, int r, int g, int b) | 设置颜色 | |
setShader(Shader shader) | 设置渐变色系 线性渐变、辐射渐变、扫描渐变等 | |
setAntiAlias(boolean aa) | 设置抗锯齿 | 还可以在Paint的构造方法中设置抗锯齿 |
setStrokeCap(Paint.Cap cap) | 设置线头形状 | 枚举值:BUTT、ROUND、SQUARE |
setStrokeCap(Paint.Cap cap):
PorterDuff.Mode:
在paint或canvas方法参数中有PorterDuff.Mode类型的参数,它是用来指定两个图像共同绘制时的颜色策略的,引用官方对16种枚举值的说明,其中src为源图像,dst为目标图像,具体可以参见https://www.jianshu.com/p/0edabe6ce8c9:
一般默认是SrcOver模式,按后绘制的遮盖先绘制的正常绘制顺序执行