Android培训之Canvas绘图基础详解.docx

上传人:牧羊曲112 文档编号:3060338 上传时间:2023-03-10 格式:DOCX 页数:31 大小:49.11KB
返回 下载 相关 举报
Android培训之Canvas绘图基础详解.docx_第1页
第1页 / 共31页
Android培训之Canvas绘图基础详解.docx_第2页
第2页 / 共31页
Android培训之Canvas绘图基础详解.docx_第3页
第3页 / 共31页
Android培训之Canvas绘图基础详解.docx_第4页
第4页 / 共31页
Android培训之Canvas绘图基础详解.docx_第5页
第5页 / 共31页
亲,该文档总共31页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《Android培训之Canvas绘图基础详解.docx》由会员分享,可在线阅读,更多相关《Android培训之Canvas绘图基础详解.docx(31页珍藏版)》请在三一办公上搜索。

1、Android培训之Canvas绘图基础详解北京尚学堂提供 Android中,如果我们想绘制复杂的自定义View或游戏,我们就需要熟悉绘图API。Android通过Canvas类暴露了很多drawXXX方法,我们可以通过这些方法绘制各种各样的图形。Canvas绘图有三个基本要素:Canvas、绘图坐标系以及Paint。Canvas是画布,我们通过Canvas的各种drawXXX方法将图形绘制到Canvas上面,在drawXXX方法中我们需要传入要绘制的图形的坐标形状,还要传入一个画笔Paint。drawXXX方法以及传入其中的坐标决定了要绘制的图形的形状,比如drawCircle方法,用来绘制

2、圆形,需要我们传入圆心的x和y坐标,以及圆的半径。drawXXX方法中传入的画笔Paint决定了绘制的图形的一些外观,比如是绘制的图形的颜色,再比如是绘制圆面还是圆的轮廓线等。Android系统的设计吸收了很多已有系统的诸多优秀之处,比如Canvas绘图。Canvas不是Android所特有的,Flex和Silverlight都支持Canvas绘图,Canvas也是HTML5标准中的一部分,主流的现代浏览器都支持用JavaScript在Canvas上绘图,如果你用过HTML5中的Canvas,你会发现Android的Canvas的绘图API与其很相似。总之,Canvas绘图不是Android所

3、特有的。 为了演示Android中各种drawXXX方法的时候,我做了一个App,通过单击相应的按钮绘制相应的图形,主界面如下所示: Canvas坐标系与绘图坐标系 Canvas绘图中牵扯到两种坐标系:Canvas坐标系与绘图坐标系。 Canvas坐标系 Canvas坐标系指的是Canvas本身的坐标系,Canvas坐标系有且只有一个,且是唯一不变的,其坐标原点在View的左上角,从坐标原点向右为x轴的正半轴,从坐标原点向下为y轴的正半轴。 绘图坐标系 Canvas的drawXXX方法中传入的各种坐标指的都是绘图坐标系中的坐标,而非Canvas坐标系中的坐标。默认情况下,绘图坐标系与Canva

4、s坐标系完全重合,即初始状况下,绘图坐标系的坐标原点也在View的左上角,从原点向右为x轴正半轴,从原点向下为y轴正半轴。但不同于Canvas坐标系,绘图坐标系并不是一成不变的,可以通过调用Canvas的translate方法平移坐标系,可以通过Canvas的rotate方法旋转坐标系,还可以通过Canvas的scale方法缩放坐标系,而且需要注意的是,translate、rotate、scale的操作都是基于当前绘图坐标系的,而不是基于Canvas坐标系,一旦通过以上方法对坐标系进行了操作之后,当前绘图坐标系就变化了,以后绘图都是基于更新的绘图坐标系了。也就是说,真正对我们绘图有用的是绘图坐

5、标系而非Canvas坐标系。 为了更好的理解绘图坐标系,请看如下的代码: /绘制坐标系 private void drawAxis(Canvas canvas) int canvasWidth = canvas.getWidth; int canvasHeight = canvas.getHeight; paint.setStyle(Paint.Style.STROKE); paint.setStrokeCap(Paint.Cap.ROUND); paint.setStrokeWidth(6 * density); /用绿色画x轴,用蓝色画y轴 /第一次绘制坐标轴 paint.setColor

6、(0xff00ff00);/绿色 canvas.drawLine(0, 0, canvasWidth, 0, paint);/绘制x轴 paint.setColor(0xff0000ff);/蓝色 canvas.drawLine(0, 0, 0, canvasHeight, paint);/绘制y轴 /对坐标系平移后,第二次绘制坐标轴 canvas.translate(canvasWidth / 4, canvasWidth /4);/把坐标系向右下角平移 paint.setColor(0xff00ff00);/绿色 canvas.drawLine(0, 0, canvasWidth, 0,

7、paint);/绘制x轴 paint.setColor(0xff0000ff);/蓝色 canvas.drawLine(0, 0, 0, canvasHeight, paint);/绘制y轴 /再次平移坐标系并在此基础上旋转坐标系,第三次绘制坐标轴 canvas.translate(canvasWidth / 4, canvasWidth / 4);/在上次平移的基础上再把坐标系向右下角平移 canvas.rotate(30);/基于当前绘图坐标系的原点旋转坐标系 paint.setColor(0xff00ff00);/绿色 canvas.drawLine(0, 0, canvasWidth,

8、 0, paint);/绘制x轴 paint.setColor(0xff0000ff);/蓝色 canvas.drawLine(0, 0, 0, canvasHeight, paint);/绘制y轴 界面如下所示: 第一次绘制绘图坐标系时,绘图坐标系默认情况下和Canvas坐标系重合,所以绘制出的坐标系紧贴View的上侧和左侧; 第二次首先将坐标轴向右下角平移了一段距离,然后绘制出的坐标系也就整体向右下角平移了; 第三次再次向右下角平移,并旋转了30度,图上倾斜的坐标系即最后的绘图坐标系。 drawARGB Canvas中的drawARGB可以用来对整个Canvas以某种统一的颜色整体绘制,四

9、个参数分别是Alpha、Red、Green、Blue,取值都是0-255。 使用代码如下: private void drawARGB(Canvas canvas) canvas.drawARGB(255, 139, 197, 186); 界面如下所示: drawText Canvas中用drawText方法绘制文字,代码如下所示: private void drawText(Canvas canvas) int canvasWidth = canvas.getWidth; int halfCanvasWidth = canvasWidth / 2; float translateY = te

10、xtHeight; /绘制正常文本 canvas.save; canvas.translate(0, translateY); canvas.drawText(正常绘制文本, 0, 0, paint); canvas.restore; translateY += textHeight * 2; /绘制绿色文本 paint.setColor(0xff00ff00);/设置字体为绿色 canvas.save; canvas.translate(0, translateY);/将画笔向下移动 canvas.drawText(绘制绿色文本, 0, 0, paint); canvas.restore;

11、paint.setColor(0xff000000);/重新设置为黑色 translateY += textHeight * 2; /设置左对齐 paint.setTextAlign(Paint.Align.LEFT);/设置左对齐 canvas.save; canvas.translate(halfCanvasWidth, translateY); canvas.drawText(左对齐文本, 0, 0, paint); canvas.restore; translateY += textHeight * 2; /设置居中对齐 paint.setTextAlign(Paint.Align.C

12、ENTER);/设置居中对齐 canvas.save; canvas.translate(halfCanvasWidth, translateY); canvas.drawText(居中对齐文本, 0, 0, paint); canvas.restore; translateY += textHeight * 2; /设置右对齐 paint.setTextAlign(Paint.Align.RIGHT);/设置右对齐 canvas.save; canvas.translate(halfCanvasWidth, translateY); canvas.drawText(右对齐文本, 0, 0,

13、paint); canvas.restore; paint.setTextAlign(Paint.Align.LEFT);/重新设置为左对齐 translateY += textHeight * 2; /设置下划线 paint.setUnderlineText(true);/设置具有下划线 canvas.save; canvas.translate(0, translateY); canvas.drawText(下划线文本, 0, 0, paint); canvas.restore; paint.setUnderlineText(false);/重新设置为没有下划线 translateY +=

14、 textHeight * 2; /绘制加粗文字 paint.setFakeBoldText(true);/将画笔设置为粗体 canvas.save; canvas.translate(0, translateY); canvas.drawText(粗体文本, 0, 0, paint); canvas.restore; paint.setFakeBoldText(false);/重新将画笔设置为非粗体状态 translateY += textHeight * 2; /文本绕绘制起点顺时针旋转 canvas.save; canvas.translate(0, translateY); canva

15、s.rotate(20); canvas.drawText(文本绕绘制起点旋转20度, 0, 0, paint); canvas.restore; 界面如下所示: 对以上代码进行一下说明: 1. Android中的画笔有两种Paint和TextPaint,我们可以Paint来画其他的图形:点、线、矩形、椭圆等。TextPaint继承自Paint,是专门用来画文本的,由于TextPaint继承自Paint,所以也可以用TextPaint画点、线、面、矩形、椭圆等图形。 2. 我们在上面的代码中将canvas.translate和canvas.rotate放到了canvas.save和canvas

16、.restore之间,这样做的好处是,在canvas.save调用时,将当前坐标系保存下来,将当前坐标系的矩阵Matrix入栈保存,然后通过translate或rotate等对坐标系进行变换,然后进行绘图,绘图完成后,我们通过调用canvas.restore将之前保存的Matrix出栈,这样就将当前绘图坐标系恢复到了canvas.save执行的时候状态。如果熟悉OpenGL开发,对这种模式应该很了解。 3. 通过调用paint.setColor(0xff00ff00)将画笔设置为绿色,paint的setColor方法需要传入一个int值,通常情况下我们写成16进制0x的形式,第一个字节存储Al

17、pha通道,第二个字节存储Red通道,第三个字节存储Green通道,第四个字节存储Blue通道,每个字节的取值都是从00到ff。如果对这种设置颜色的方式不熟悉,也可以调用paint.setARGB(int a, int r, int g, int b)方法设置画笔的颜色,不过paint.setColor(int color)的方式更简洁。 4. 通过调用paint.setTextAlign设置文本的对齐方式,该对齐方式是相对于绘制文本时的画笔的坐标来说的,在本例中,我们绘制文本时画笔在Canvas宽度的中间。在drawText方法执行时,需要传入一个x和y坐标,假设该点为P点,P点表示我们从P

18、点绘制文本。当对齐方式为Paint.Align.LEFT时,绘制的文本以P点为基准向左对齐,这是默认的对齐方式;当对齐方式为Paint.Align.CENTER时,绘制的文本以P点为基准居中对齐;当对齐方式为Paint.Align.RIGHT时,绘制的文本以P点为基准向右对齐。 5. 通过调用paint.setUnderlineText(true)绘制带有下划线的文本。 6. 通过调用paint.setFakeBoldText(true)绘制粗体文本。 7. 通过rotate旋转坐标系,我们可以绘制倾斜文本。 drawPoint Canvas中用drawPoint方法绘制点,代码如下所示: p

19、rivate void drawPoint(Canvas canvas) int canvasWidth = canvas.getWidth; int canvasHeight = canvas.getHeight; int x = canvasWidth / 2; int deltaY = canvasHeight / 3; int y = deltaY / 2; paint.setColor(0xff8bc5ba);/设置颜色 paint.setStrokeWidth(50 * density);/设置线宽,如果不设置线宽,无法绘制点 /绘制Cap为BUTT的点 paint.setStro

20、keCap(Paint.Cap.BUTT); canvas.drawPoint(x, y, paint); /绘制Cap为ROUND的点 canvas.translate(0, deltaY); paint.setStrokeCap(Paint.Cap.ROUND); canvas.drawPoint(x, y, paint); /绘制Cap为SQUARE的点 canvas.translate(0, deltaY); paint.setStrokeCap(Paint.Cap.SQUARE); canvas.drawPoint(x, y, paint); 界面如下所示: 下面对以上代码进行说明:

21、 1. Paint的setStrokeWidth方法可以控制所画线的宽度,通过Paint的getStrokeWidth方法可以得到所画线的宽度,默认情况下,线宽是0。其实strokeWidth不仅对画线有影响,对画点也有影响,由于默认的线宽是0,所以默认情况下调用drawPoint方法无法在Canvas上画出点,为了让大家清楚地看到所画的点,我用Paint的setStrokeWidth设置了一个比较大的线宽,这样我们看到的点也就比较大。 2. Paint有个setStrokeCap方法可以设置所画线段的时候两个端点的形状,即所画线段的帽端的形状,在下面讲到drawLine方法时会详细说明,其实

22、setStrokeCap方法也会影响所画点的形状。Paint的setStrokeCap方法可以有三个取值:Paint.Cap.BUTT、Paint.Cap.ROUND和Paint.Cap.SQUARE。 3. 默认情况下Paint的getStrokeCap的返回值是Paint.Cap.BUTT,默认画出来的点就是一个正方形,上图第一个点即是用BUTT作为帽端画的。 4. 我们可以调用setStrokeCap方法设置Paint的strokeCap为Paint.Cap.ROUND时,画笔画出来的点就是一个圆形,上图第二个点即是用ROUND作为帽端画的。 5. 调用调用setStrokeCap方法设

23、置Paint的strokeCap为Paint.Cap.SQUARE时,画笔画出来的电也是一个正方形,与用BUTT画出来的效果在外观上相同,上图最后一个点即时用SQUARE作为帽端画的。 drawLine Canvas通过drawLine方法绘制一条线段,通过drawLines方法绘制多段线,使用代码如下所示: 下面对以上代码进行说明: 1. drawLine方法接收四个数值,即起点的x和y以及终点的x和y,绘制一条线段。 2. drawLines方法接收一个float数组pts,需要注意的是在用drawLines绘图时,其每次从pts数组中取出四个点绘制一条线段,然后再取出后面四个点绘制一条线

24、段,所以要求pts的长度需要是4的倍数。假设我们有四个点,分别是p1、p2、p3、p4,我们依次将其坐标放到pts数组中,即pts = p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y,那么用drawLines绘制pts时,你会发现p1和p2之间画了一条线段,p3和p4之间画了一条线段,但是p2和p3之间没有画线段,这样大家就应该能明白drawLines每次都需要从pts数组中取出4个值绘制一条线段的意思了。 3. 通过调用Paint的setStrokeWidth方法设置线的宽度。 4. 上面在讲drawPoint时提到了strokeCap对所绘制点

25、的形状的影响,通过drawLine绘制的线段也受其影响,体现在绘制的线段的两个端点的形状上。 o Paint.Cap.BUTT 当用BUTT作为帽端时,所绘制的线段恰好在起点终点位置处戛然而止,两端是方形,上图中第一条加粗的线段就是用BUTT作为帽端绘制的。 o Paint.Cap.ROUND 当用ROUND作为帽端时,所绘制的线段的两端端点会超出起点和终点一点距离,并且两端是圆形状,上图中第二条加粗的线段就是用ROUND作为帽端绘制的。 o Paint.Cap.SQUARE 当用SQUARE作为帽端时,所绘制的线段的两端端点也会超出起点和终点一点距离,两端点的形状是方形,上图中最后一条加粗的

26、线段就是用SQUARE作为帽端绘制的。 drawRect Canvas通过drawRect方法绘制矩形,使用代码如下所示: private void drawRect(Canvas canvas) int canvasWidth = canvas.getWidth; int canvasHeight = canvas.getHeight; /默认画笔的填充色是黑色 int left1 = 10; int top1 = 10; int right1 = canvasWidth / 3; int bottom1 = canvasHeight /3; canvas.drawRect(left1, t

27、op1, right1, bottom1, paint); /修改画笔颜色 paint.setColor(0xff8bc5ba);/A:ff,R:8b,G:c5,B:ba int left2 = canvasWidth / 3 * 2; int top2 = 10; int right2 = canvasWidth - 10; int bottom2 = canvasHeight / 3; canvas.drawRect(left2, top2, right2, bottom2, paint); 界面如下所示: 其方法签名是drawRect(float left, float top, flo

28、at right, float bottom, Paint paint),left和right表示矩形的左边和右边分别到绘图坐标系y轴正半轴的距离,top和bottom表示矩形的上边和下边分别到绘图坐标系x轴正半轴的距离。 drawCircle Canvas中用drawCircle方法绘制圆形,使用代码如下所示: private void drawCircle(Canvas canvas) paint.setColor(0xff8bc5ba);/设置颜色 paint.setStyle(Paint.Style.FILL);/默认绘图为填充模式 int canvasWidth = canvas.g

29、etWidth; int canvasHeight = canvas.getHeight; int halfCanvasWidth = canvasWidth / 2; int count = 3; int D = canvasHeight / (count + 1); int R = D / 2; /绘制圆 canvas.translate(0, D / (count + 1); canvas.drawCircle(halfCanvasWidth, R, R, paint); /通过绘制两个圆形成圆环 /1. 首先绘制大圆 canvas.translate(0, D + D / (count

30、 + 1); canvas.drawCircle(halfCanvasWidth, R, R, paint); /2. 然后绘制小圆,让小圆覆盖大圆,形成圆环效果 int r = (int)(R * 0.75); paint.setColor(0xffffffff);/将画笔设置为白色,画小圆 canvas.drawCircle(halfCanvasWidth, R, r, paint); /通过线条绘图模式绘制圆环 canvas.translate(0, D + D / (count + 1); paint.setColor(0xff8bc5ba);/设置颜色 paint.setStyle(

31、Paint.Style.STROKE);/绘图为线条模式 float strokeWidth = (float)(R * 0.25); paint.setStrokeWidth(strokeWidth); canvas.drawCircle(halfCanvasWidth, R, R, paint); 界面如下所示: 下面对以上代码进行说明: 1. 其方法签名是drawCircle (float cx, float cy, float radius, Paint paint),在使用时需要传入圆心的坐标以及半径,当然还有画笔Paint对象。 2. 当我们在调用drawCircle、drawOv

32、al、drawArc、drawRect等方法时,我们既可以绘制对应图形的填充面,也可以只绘制该图形的轮廓线,控制的关键在于画笔Paint中的style。Paint通过setStyle方法设置要绘制的类型,style有取三种值:Paint.Style.FILL、Paint.Style.STROKE和Paint.Style.FILL_AND_STROKE。 o 当style为FILL时,绘制是填充面,FILL是Paint默认的style; o 当style为STROKE时,绘制的是图形的轮廓线; o 当style为FILL_AND_STROKE时,同时绘制填充面和轮廓线,不过这种情况用的不多,因为

33、填充面和轮廓线是用同一种颜色绘制的,区分不出轮廓线的效果。 3. 在Paint的style是FILL时,我们通过drawCircle绘制出圆面,如上图中的第一个图形所示。 4. 我们可以通过绘制两个圆面的方式绘制出圆环的效果。首先将画笔设置为某一颜色,且style设置为FILL状态,通过drawCircle绘制一个大的圆面;然后将画笔Paint的颜色改为白色或其他颜色,并减小半径再次通过drawCircle绘制一个小圆,这样就用小圆遮盖了大圆的一部分,未遮盖的部分便自然形成了圆环的效果,如上图中的第二个图形所示。 5. 除了上述方法,我们还有一种办法绘制圆环的效果。我们首先将画笔Paint的s

34、tyle设置为STROKE模式,表示画笔处于画线条模式,而非填充模式。然后为了让圆环比较明显有一定的宽度,我们需要调用Paint的setStrokeWidth方法设置线宽。最后调用drawCircle方法绘制出宽度比较大的圆的轮廓线,也就形成了圆环效果,如上图中的最后一个图形所示。此处需要说明的是,当我们用STROKE模式画圆时,轮廓线是以实际圆的边界为分界线分别向内向外扩充1/2的线宽的距离,比如圆的半径是100,线宽是20,那么在STROKE模式下绘制出的圆环效果相当于半径为110的大圆和半径为90的小圆形成的效果,100 + 20 / 2 = 110, 100 - 20/2 = 90。

35、drawOval Canvas中提供了drawOval方法绘制椭圆,其使用代码如下所示: private void drawOval(Canvas canvas) int canvasWidth = canvas.getWidth; int canvasHeight = canvas.getHeight; float quarter = canvasHeight / 4; float left = 10 * density; float top = 0; float right = canvasWidth - left; float bottom= quarter; RectF rectF =

36、 new RectF(left, top, right, bottom); /绘制椭圆形轮廓线 paint.setStyle(Paint.Style.STROKE);/设置画笔为画线条模式 paint.setStrokeWidth(2 * density);/设置线宽 paint.setColor(0xff8bc5ba);/设置线条颜色 canvas.translate(0, quarter / 4); canvas.drawOval(rectF, paint); /绘制椭圆形填充面 paint.setStyle(Paint.Style.FILL);/设置画笔为填充模式 canvas.tran

37、slate(0, (quarter + quarter / 4); canvas.drawOval(rectF, paint); /画两个椭圆,形成轮廓线和填充色不同的效果 canvas.translate(0, (quarter + quarter / 4); /1. 首先绘制填充色 paint.setStyle(Paint.Style.FILL);/设置画笔为填充模式 canvas.drawOval(rectF, paint);/绘制椭圆形的填充效果 /2. 将线条颜色设置为蓝色,绘制轮廓线 paint.setStyle(Paint.Style.STROKE);/设置画笔为线条模式 pai

38、nt.setColor(0xff0000ff);/设置填充色为蓝色 canvas.drawOval(rectF, paint);/设置椭圆的轮廓线 其界面如下所示: 下面对以上代码进行说明: 1. 其方法签名是public void drawOval (RectF oval, Paint paint),RectF有四个字段,分别是left、top、right、bottom, 这四个值对应了椭圆的左、上、右、下四个点到相应坐标轴的距离,具体来说,left和right表示椭圆的最左侧的点和最右侧的点到绘图坐标系的y轴的距离,top和bottom表示椭圆的最顶部的点和最底部的点到绘图坐标系的x轴的距

39、离,这四个值就决定了椭圆的形状,right与left的差值即为椭圆的长轴,bottom与top的差值即为椭圆的短轴,如下图所示: 2. 通过Paint的setStyle方法将画笔的style设置成STROKE,即画线条模式,这种情况下,用画笔画出来的是椭圆的轮廓线,而非填充面,如上图中的第一个图形所示。 3. 当将画笔Paint的style设置为FILL时,即填充模式,这种情况下,用画笔画出来的是椭圆的填充面,如上图中的第二个图形所示。 4. 如果我们想绘制带有其他颜色轮廓线的椭圆面,我们需要绘制两个椭圆。首先以FILL模式画一个椭圆的填充面,然后更改画笔颜色,以STROKE模式画椭圆的轮廓线

40、,如上图中的最后一个图形所示。这样从外观上看,好像是椭圆面与椭圆的轮廓线颜色不同。 drawArc Canvas中提供了drawArc方法用于绘制弧,这里的弧指两种:弧面和弧线,弧面即用弧围成的填充面,弧线即为弧面的轮廓线。其使用代码如下所示: private void drawArc(Canvas canvas) int canvasWidth = canvas.getWidth; int canvasHeight = canvas.getHeight; int count = 5; float ovalHeight = canvasHeight / (count + 1); float l

41、eft = 10 * density; float top = 0; float right = canvasWidth - left; float bottom= ovalHeight; RectF rectF = new RectF(left, top, right, bottom); paint.setStrokeWidth(2 * density);/设置线宽 paint.setColor(0xff8bc5ba);/设置颜色 paint.setStyle(Paint.Style.FILL);/默认设置画笔为填充模式 /绘制用drawArc绘制完整的椭圆 canvas.translate

42、(0, ovalHeight / count); canvas.drawArc(rectF, 0, 360, true, paint); /绘制椭圆的四分之一,起点是钟表的3点位置,从3点绘制到6点的位置 canvas.translate(0, (ovalHeight + ovalHeight / count); canvas.drawArc(rectF, 0, 90, true, paint); /绘制椭圆的四分之一,将useCenter设置为false canvas.translate(0, (ovalHeight + ovalHeight / count); canvas.drawArc(rectF, 0, 90, false, paint); /绘制椭圆的四分之一,只绘制轮廓线 paint.setStyle(Paint.Style.STROKE);/设置画笔为线条模式 canvas.translate(0, (ovalHeight + ovalHeight / count); canvas.drawArc(rectF, 0, 90, true, paint); /绘制带有轮廓线

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号