自定义绘制概述
- 方法:重写绘制方法(最常用:onDraw())
- 绘制的关键:Canvas
- Canvas的绘制类方法:drawXXX()(关键参数:Paint)
- Canvas的辅助类方法:范围裁切(clipXXX())和几何变换(Matrix)
- 使用不同的绘制方法来控制遮盖关系
自定义绘制知识的四个级别
- Canvas 的 drawXXX() 系列方法及 Paint 最常见的使用
- Paint 的完全攻略
- Canvas 对绘制的辅助——范围裁切和几何变换。
- 使用不同的绘制方法来控制绘制顺序
一切的开始:onDraw()
自定义绘制的上手非常容易:提前创建好 Paint 对象,重写 onDraw(),把绘制代码写在 onDraw() 里面,就是自定义绘制最基本的实现。
Canvas.drawXXX() 和 Paint 基础
drawXXX() 系列方法和 Paint 的基础掌握了,就能够应付简单的绘制需求。它们主要包括:
-
Canvas 类下的所有 draw- 打头的方法,例如 drawCircle() drawBitmap()。
- Canvas.drawColor(@ColorInt int color) 颜色填充
- drawCircle(float centerX, float centerY, float radius, Paint paint) 画圆
- drawRect(float left, float top, float right, float bottom, Paint paint) 画矩形
- drawPoint(float x, float y, Paint paint) 画点
- drawPoints(float[] pts, int offset, int count, Paint paint) / drawPoints(float[] pts, Paint paint) 画点(批量)
- drawOval(float left, float top, float right, float bottom, Paint paint) 画椭圆
- drawLine(float startX, float startY, float stopX, float stopY, Paint paint) 画线
- drawLines(float[] pts, int offset, int count, Paint paint) / drawLines(float[] pts, Paint paint) 画线(批量)
- drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint) 画圆角矩形
- drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, Paint paint) 绘制弧形或扇形
- drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, Paint paint) 绘制弧形或扇形
- drawBitmap(Bitmap bitmap, float left, float top, Paint paint) 画 Bitmap
- drawText(String text, float x, float y, Paint paint) 绘制文字
left, top, right, bottom 是矩形四条边
-
Paint 类的几个最常用的方法。具体是:
- Paint.setStyle(Style style) 设置绘制模式
- Paint.setColor(int color) 设置颜色
- Paint.setStrokeWidth(float width) 设置线条宽度
- Paint.setTextSize(float textSize) 设置文字大小
- Paint.setAntiAlias(boolean aa) 设置抗锯齿开关
插曲1
-
一个 View 的坐标 (x, y) 处,指的就是相对它的左上角那个点的水平方向 x 像素、竖直方向 y 像素的点。例如,(300, 300) 指的就是左上角的点向右 300 、向下 300 的位置; (100, -50) 指的就是左上角的点向右 100 、向上 50 的位置。也就是说, canvas.drawCircle(300, 300, 200, paint) 这行代码绘制出的圆,在 View 中的位置和尺寸应该是这样的:
插播一: Paint.setColor(int color)
你要画一个红色的圆,并不是写成 canvas.drawCircle(300, 300, 200, RED, paint) 这样,而是像下面这样:
paint.setColor(Color.RED); // 设置为红色
canvas.drawCircle(300, 300, 200, paint);
插播二: Paint.setStyle(Paint.Style style)
如果你想画的不是实心圆,而是空心圆(或者叫环形),也可以使用 paint.setStyle(Paint.Style.STROKE) 来把绘制模式改为画线模式。
paint.setStyle(Paint.Style.STROKE); // Style 修改为画线模式
canvas.drawCircle(300, 300, 200, paint);
setStyle(Style style) 这个方法设置的是绘制的 Style 。Style 具体来说有三种: FILL, STROKE 和 FILL_AND_STROKE 。FILL 是填充模式,STROKE 是画线模式(即勾边模式),FILL_AND_STROKE 是两种模式一并使用:既画线又填充。它的默认值是 FILL,填充模式。
插播三: Paint.setStrokeWidth(float width)
在 STROKE 和 FILL_AND_STROKE 下,还可以使用 paint.setStrokeWidth(float width) 来设置线条的宽度:
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(20); // 线条宽度为 20 像素
canvas.drawCircle(300, 300, 200, paint);
插播四: 抗锯齿
在绘制的时候,往往需要开启抗锯齿来让图形和文字的边缘更加平滑。开启抗锯齿很简单,只要在 new Paint() 的时候加上一个 ANTI_ALIAS_FLAG 参数就行:
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
插曲2 (drawPath画自定义图形)
drawPath(path) 这个方法是通过描述路径的方式来绘制图形的,它的 path 参数就是用来描述图形路径的对象。path 的类型是 Path ,使用方法大概像下面这样:
public class PathView extends View {
Paint paint = new Paint();
Path path = new Path(); // 初始化 Path 对象
......
{
// 使用 path 对图形进行描述(这段描述代码不必看懂)
path.addArc(200, 200, 400, 400, -225, 225);
path.arcTo(400, 200, 600, 400, -180, 225, false);
path.lineTo(400, 542);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(path, paint); // 绘制出 path 描述的图形(心形),大功告成
}
}
Path 可以描述直线、二次曲线、三次曲线、圆、椭圆、弧形、矩形、圆角矩形。把这些图形结合起来,就可以描述出很多复杂的图形。下面我就说一下具体的怎么把这些图形描述出来。
Path 可以描述直线、二次曲线、三次曲线、圆、椭圆、弧形、矩形、圆角矩形。把这些图形结合起来,就可以描述出很多复杂的图形。下面我就说一下具体的怎么把这些图形描述出来。
这一类方法还可以细分为两组:添加子图形和画线(直线或曲线)
第一组: addXxx() ——添加子图形
addCircle(float x, float y, float radius, Direction dir) 添加圆
路径方向有两种:顺时针 (CW clockwise) 和逆时针 (CCW counter-clockwise) 。对于普通情况,这个参数填 CW 还是填 CCW 没有影响。它只是在需要填充图形 (Paint.Style 为 FILL 或 FILL_AND_STROKE) ,并且图形出现自相交时,用于判断填充范围的。
是应该填充成这样呢:
还是应该填充成这样呢:
addOval(float left, float top, float right, float bottom, Direction dir) / addOval(RectF oval, Direction dir) 添加椭圆
addRect(float left, float top, float right, float bottom, Direction dir) / addRect(RectF rect, Direction dir) 添加矩形
addRoundRect(RectF rect, float rx, float ry, Direction dir) / addRoundRect(float left, float top, float right, float bottom, float rx, float ry, Direction dir) /
addRoundRect(RectF rect, float[] radii, Direction dir) / addRoundRect(float left, float top, float right, float bottom, float[] radii, Direction dir) 添加圆角矩形
addPath(Path path) 添加另一个 Path
第二组:xxxTo() ——画线(直线或曲线)
这一组和第一组 addXxx() 方法的区别在于,第一组是添加的完整封闭图形(除了 addPath() ),而这一组添加的只是一条线。
lineTo(float x, float y) / rLineTo(float x, float y) 画直线
quadTo(float x1, float y1, float x2, float y2) / rQuadTo(float dx1, float dy1, float dx2, float dy2) 画二次贝塞尔曲线
cubicTo(float x1, float y1, float x2, float y2, float x3, float y3) / rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3) 画三次贝塞尔曲线
moveTo(float x, float y) / rMoveTo(float x, float y) 移动到目标位置
arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo) / arcTo(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo) / arcTo(RectF oval, float startAngle, float sweepAngle) 画弧形
addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle) / addArc(RectF oval, float startAngle, float sweepAngle) 画弧形
close() 封闭当前子图形
Path 方法第二类:辅助的设置或计算
Path.setFillType(Path.FillType ft) 设置填充方式
Path.setFillType(Path.FillType ft) 设置填充方式
本文参考自HenCoder系列http://http://hencoder.com/