Android 的绘制是一个庞大的工程,我了解的也不全,这里就把我学习的路线写一下。基本是按照 扔物线 的自定义 View 课程来学习的,他的网站:http://hencoder.com
我们通过往布局当中添加一个 TextView 控件来添加一行文字,添加一个 ImageView 来添加一张图片,实际上,这些文字、图片等等都是通过绘制展现在我们面前的。
如果我们需要绘制自己的组件,就需要去让我们的类去重写 onDraw 方法,所有的绘制操作都是在该方法中进行的。
onDraw 方法的参数是一个 Canvas,翻译过来是“画布”,实际上,Canvas 的功能却不单单是画布这么简单,我们的所有内容都是 Canvas “画”出来的,所以 Canvas 不单单是一个画布的功能。
Android 还有一个重要的对象:Paint,翻译过来是“颜料”,实际上它的功能是为我们“作画的画笔”提供一系列的设置操作,譬如颜色、风格等等。
Canvas 提供了一系列的 “drawXXX” 方法来帮助我们去画出我们需要的内容,点、线、圆(椭圆)、矩形、文字、图片等等。
在讲解图形绘制之前,先将一个重要的参数,几乎每一个 drawXXX 方法都有一个 paint 参数,该参数定义了画笔的一系列属性:实心空心、笔触宽度、画笔颜色、是否消除锯齿等等。
在这里把最常用的设置列一下,没有将到的后面遇到了再提。
setStyle:设置画笔的风格,主要有三种:
setStrokeCap:设置笔帽风格。有以下几种风格可选:
常用的方法就是这几个,但是还有一些更加高级的用法,在后面会讲到。
Canvas 的 setColor 和 setARGB 都是用来绘制颜色的:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//两种效果颜色是一样的
canvas.drawColor(Color.parseColor("#FFF68F"));
canvas.drawARGB(255, 255, 246, 143);
}
这里的绘制颜色和 Paint 的 setColor 是不一样是,这个是绘制整个画布的颜色。
在 Android 中有两个方法可以画点:
使用 drawPoint 方法需要设置画笔宽度,否则效果不明显。
示例:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setStrokeWidth(50);
paint.setColor(Color.RED);
float[] points = new float[]{100,100,200,200,300,300,400,400};
canvas.drawPoints(points,paint);
paint.setColor(Color.BLUE);
canvas.drawPoints(points,1,3,paint);
}
效果:
可以看到,蓝色点因为取了三个值,只能构成一个点,所以只画出一个。
连接两点,形成直线。
可以调用 Canvas 对象的 drawRect 来画一个矩形,也可以调用 drawRoungdRect 来画一个圆角矩形。
说一下 Rect 和 RectF,通俗一点讲就是,Rect 封装了一个矩形四个边的 X/Y 轴数据,RectF 和 Rect 的不同点就是四个边的距离可以是 float...
再说圆角的半径,如果 X/Y 轴半径相同,则是一个规则的圆(角),X 轴数据和 Y 轴不同,就是一个椭圆(角),X>Y 是一个横着的椭圆,Y>X 是一个竖起来的椭圆。
示例:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setStrokeWidth(10);
paint.setColor(Color.RED);
canvas.drawRect(100, 100, 500, 500, paint);//画正方形
paint.setColor(Color.GREEN);
paint.setStyle(Paint.Style.STROKE);
canvas.drawRect(new Rect(600, 100, 900, 1000), paint);//画空心长方形
paint.setColor(Color.BLUE);
canvas.drawRoundRect(100, 700, 500, 1000, 20, 20, paint);//画圆角空心长方形
}
效果:
调用 Canvas 的 drawCircle 来画一个圆,drawOval 来画一个椭圆。
drawCircle(float cx, float cy, float radius, Paint paint):画圆,参数说明:
drawOval(RectF oval, Paint paint):通过 RectF 画一个椭圆。
示例:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setStrokeWidth(10);
paint.setColor(Color.RED);
canvas.drawCircle(500, 500, 200, paint);
paint.setStyle(Paint.Style.STROKE);
canvas.drawOval(100, 800, 900, 900, paint);
}
效果如下:
调用 Canvas 对象的 drawArc 方法可以画出圆弧。
如果 Paint 对象的 Style 为
FILL
或者FILL_AND_STROKE
,则效果为扇形
参数说明:
示例:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setStrokeWidth(5);//画笔笔触宽度
paint.setColor(Color.RED);//画笔颜色
paint.setStyle(Paint.Style.STROKE);//空心
//为演示圆弧和 RectF 的关系,先画几个矩形。
RectF rect1 = new RectF(100, 100, 400, 400);
RectF rect2 = new RectF(100, 500, 400, 800);
RectF rect3 = new RectF(100, 900, 400, 1200);
RectF rect4 = new RectF(100, 1300, 400, 1600);
canvas.drawRect(rect1, paint);//为展示方便,画一个矩形
canvas.drawRect(rect2, paint);//为展示方便,画一个矩形
canvas.drawRect(rect3, paint);//为展示方便,画一个矩形
canvas.drawRect(rect4, paint);//为展示方便,画一个矩形
paint.setColor(Color.GREEN);//将画笔颜色改为绿色,开始画圆弧
//第一个圆弧,起始角度90°,旋转角度90°,使用圆心,并且不填充
paint.setStyle(Paint.Style.STROKE); //不填充
canvas.drawArc(rect1, 90, 90, true, paint);//使用圆心
//第二个圆弧,起始角度90°,旋转角度90°,不使用圆心,空心
canvas.drawArc(rect2, 90, 90, false, paint);//不使用圆心
//第三个圆弧,起始角度180°,旋转角度120°,使用圆心,填充(扇形)
paint.setStyle(Paint.Style.FILL_AND_STROKE);//实心
canvas.drawArc(rect3, 180, 120, true, paint);//使用圆心
//第四个圆弧,起始角度 180°,120°,不使用圆心,填充(扇形)
canvas.drawArc(rect4, 180, 120, false, paint);
}
效果如下:
用来绘制 Bitmap 对象,将 Bitmap 中的像素内容复制过来。
示例:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setStrokeWidth(5);//画笔笔触宽度
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.timg);
canvas.drawBitmap(bitmap, 0, 0, paint);
Rect rect = new Rect(0, 0, 600, 600);
canvas.drawBitmap(bitmap, rect, new Rect(0, 700, 600, 1300), paint);
}
显示如下:
通过调用 Canvas 对象的 drawText 方法来绘制文字
先来看一个简单的例子:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setTextSize(300);
canvas.drawText("Google", 0, 0, paint);
}
显示结果:
这是因为啥呢?画一个矩形的时候,坐标都是以四个边为标准的,而绘制文字却不是,其坐标标准是有一个“baseline”的:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int baseLine = 500;
paint.setTextSize(300);
canvas.drawText("Google", 200, baseLine, paint);
//添加一条辅助线,更直观的观察 BaseLine
paint.setStrokeWidth(5);
paint.setColor(Color.RED);
canvas.drawLine(0, baseLine, canvas.getWidth(), baseLine, paint);
}
显示如下:
是不是对 drawText 的位置是不是很明白了,其实 drawText 单位绘制有很多讲究,后面再深入写吧。
在屏幕中间画一个饼状图,饼状图分为五部分,分别为 40%,10%,30%,15%,5%,每个部分都为不同颜色。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.parseColor("#FFFAF0"));
int canvasWidth = canvas.getWidth();
int canvasHeight = canvas.getHeight();
float left = canvasWidth / 4;
float top = (canvasHeight - (canvasWidth / 2)) / 2;
float right = canvasWidth * 3 / 4;
float bottom = ((canvasHeight - (canvasWidth / 2)) / 2) + (canvasWidth / 2);
RectF rectF = new RectF(left, top, right, bottom);
Log.d("TTT", "width = " + canvasWidth);
Log.d("TTT", "height = " + canvasHeight);
Log.d("TTT","left = " + left);
Log.d("TTT","top = " + top);
Log.d("TTT","right = " + right);
Log.d("TTT","bottom = " + bottom);
//开始画饼状图。
paint.setColor(Color.RED);
canvas.drawArc(rectF, 0, 360 * 40 / 100, true, paint);
paint.setColor(Color.BLUE);
canvas.drawArc(rectF, 360 * 40 / 100, 360 * 10 / 100, true, paint);
paint.setColor(Color.GREEN);
canvas.drawArc(rectF, (360 * 40 / 100) + (360 * 10 / 100), 360 * 30 / 100, true, paint);
paint.setColor(Color.GRAY);
canvas.drawArc(rectF, (360 * 40 / 100) + (360 * 10 / 100) + (360 * 30 / 100), 360 * 15 / 100, true, paint);
paint.setColor(Color.YELLOW);
canvas.drawArc(rectF, (360 * 40 / 100) + (360 * 10 / 100) + (360 * 30 / 100) + (360 * 15 / 100), 360 * 5 / 100, true, paint);
//中间画一个圆,让这个饼状图变成空心。
paint.setColor(Color.parseColor("#FFFAF0"));
canvas.drawCircle(canvasWidth / 2, canvasHeight / 2, 200, paint);
}
参数没啥可解释的,简单的加减法,显示如下: