今晚瞎折腾,闲着没事画了个机器人——android,浪费了一个晚上的时间。画 这丫还真不容易,为那些坐标,差点砸了键盘,好在最后画出个有模有样的,心 稍安。 下面来看看画这么个机器人需要些什么东西:主要是 Canvas 类 (android.graphics.Canvas)。Canvas 类就是表示一块画布,你可以在上面画你 想画的东西。当然,你还可以设置画布的属性,如画布的颜色
/尺寸等。Canvas 提供了如下一些方法:
Canvas():创建一个空的画布,可以使用 setBitmap()方法来设置绘制的具体画 布;
Canvas(Bitmap bitmap):以 bitmap 对象创建一个画布,则将内容都绘制在
bitmap 上,bitmap 不得为 null;
Canvas(GL gl):在绘制3D 效果时使用,与 OpenGL 有关;
drawColor:设置画布的背景色;
setBitmap:设置具体的画布;
clipRect:设置显示区域,即设置裁剪区;
isOpaque:检测是否支持透明;
rotate:旋转画布; 下面我们就用 Canvas 来画一个机器人——android,oh my love!一看就知道,机 器人的外形是由矩形/圆/圆弧/线条组成的,因此要知道怎么用 Canvas 画矩形/ 圆/圆弧和线条。可惜阿,上面几个方法基本都没用上。
canvas.drawRect(RectF,Paint)方法用于画矩形,第一个参数为图形显示区域, 第二个参数为画笔,设置好图形显示区域 Rect 和画笔 Paint 后,即可画图;
canvas.drawRoundRect(RectF, float, float, Paint) 方法用于画圆角矩形, 第一个参数为图形显示区域, 第二个参数和第三个参数分别是水平圆角半径和垂 直圆角半径。
canvas.drawLine(startX, startY, stopX, stopY, paint):前四个参数的类型 均为 float, 最后一个参数类型为 Paint。 表示用画笔 paint 从点 (startX,startY) 到点(stopX,stopY)画一条直线;
canvas.drawArc(oval, startAngle, sweepAngle, useCenter, paint):第一个 参数 oval 为 RectF 类型, 即圆弧显示区域, startAngle 和 sweepAngle 均为 float 类型,分别表示圆弧起始角度和圆弧度数,3点钟方向为0度,useCenter 设置是 否显示圆心,boolean 类型,paint 为画笔;
canvas.drawCircle(float,float, float, Paint)方法用于画圆,前两个参数代 表圆心坐标,第三个参数为圆半径,第四个参数是画笔;
清楚这些函数的用法之后,我们是否就噼里啪啦地敲代码了呢?别急,我们来搞 个设计。既然这些函数都是用来画图的,也就是说它们有共性——画。所有我们 应该设计一个接口 interface,对于这次任务,只需要一个成员方法就足够了。 对于每一个图形,是只用一个方法画,还是将画图封装成类呢?我建议是封装成 类。因为说不定你明天就会嫌弃它不会动,想它动起来,或者你过两天又希望在 机器人的每个部位加点什么。所以我将每一个图形封装成类,都实现一个名叫 drawGraphics 的接口。最后,要记得给 UI 创建一个线程哦。
就这样我开始动手做了,但是很快就发现问题了。什么问题?在定位的时候,也 就是设置每个图形的显示区域时,我自以为这里的 Rect 跟 Java 的 Rectangle 是一样的,但我错了。原来这厮跟 MFC 中的 RECT 结构才是一家人,害我折腾了 许久。
Rect(int left,int top,int right,int bottom) left 矩形左上角 X 坐标值 top 矩形左上角 Y 坐标值 right 矩形右下角 X 坐标值 bottom
矩形右下角 Y 坐标值
下面借用一张图说明(忘了哪个博客找来的(*^__^*) 嘻嘻……) ,如 Rect(150, 75, 260, 120) 一目了然吧。
还有一点非常重要的是,屏幕最上方的状态栏和标题栏总占去来50的高度,同时 坐标原点下移到标题栏下方,即如果你的手机屏幕分辨率为(320X480) ,编程时 如果没有设置去除状态栏和标题栏,你只能操控的范围只有(320X430) ,而且坐 标原点下移。记住咯。
//drawGraphics.java package com.scgm.android.drawable; importandroid.graphics.Canvas; import publicinterface drawGraphics { publicvoid draw(Canvas canvas); }
package com.scgm.android.drawable;
importandroid.content.Context; import import android.graphics.Canvas; importandroid.graphics.Color; import importandroid.graphics.Paint; import importandroid.view.View; import
publicclassGameViewextends extendsViewimplements Runnable{ publicclass extends implements
//声明 Paint 对象 null; private Paint mPaint= null privatedrawGraphics drawGraphics= null null; private publicGameView(Context context) { public super(context); super // TODO TODOAuto-generated constructor stub //构建对象 mPaint= new newPaint(); //开启线程 this).start(); new Thread(this this }
publicvoid onDraw(Canvas canvas) { super.onDraw(canvas); super //设置画布为黑色背景 //canvas.drawColor(Color.BLACK); //消除锯齿 mPaint.setAntiAlias(true true); true //设置图形为空心 mPaint.setStyle(Paint.Style.STROKE); //绘制空心几何图形 drawGraphics=new DrawCircle(); new
drawGraphics.draw(canvas); drawGraphics=new DrawLine(); new drawGraphics.draw(canvas); drawGraphics= new newDrawRect(); drawGraphics.draw(canvas); }
@Override publicvoidrun() { publicvoid // TODO TODOAuto-generated method stub while(!Thread.currentThread().isInterrupted()) { while try{ try Thread.sleep(1000); } catch catch(InterruptedException e) { // TODO handle exception TODO: Thread.currentThread().interrupt(); } //使用 postInvalidate 可以直接在线程中更新界面 postInvalidate(); } } }
//DrawRect.java packagecom.scgm.android.drawable; package
importandroid.graphics.Canvas; import importandroid.graphics.Color; import importandroid.graphics.Paint; import importandroid.graphics.RectF; import
publicclassDrawRectimplements drawGraphics{ implements publicclass null; private Paint paint=null null publicDrawRect(){ public paint= new Paint(); }
@Override publicvoid draw(Canvas canvas) { // TODO TODOAuto-generated method stub //定义圆角矩形对象 RectF rectF1 = new newRectF(120,170,370,500); RectF rectF2 = new newRectF(40,150,90,400); RectF rectF3 = new newRectF(390,150,440,400); RectF rectF4 = new newRectF(140,520,200,650);
RectF rectF5 = new newRectF(290,520,350,650); paint.setAntiAlias(true true); true //设置画笔颜色为 BLUE paint.setColor(Color.GREEN); //在画布上绘制圆角矩形/圆弧/直线 canvas.drawRoundRect(rectF1, 20, 20, paint); canvas.drawRoundRect(rectF2, 20, 20, paint); canvas.drawRoundRect(rectF3, 20, 20, paint); canvas.drawRoundRect(rectF4, 20, 20, paint); canvas.drawRoundRect(rectF5, 20, 20, paint); } }
//DrawLine.java package com.scgm.android.drawable;
importandroid.graphics.Canvas; import import android.graphics.Color; importandroid.graphics.Paint; import publicclassDrawLineimplements drawGraphics{ implements publicclass privatePaint paint=null null; private null public DrawLine(){
paint=new Paint(); new }
@Override publicvoiddraw(Canvas canvas) { publicvoid // TODO TODOAuto-generated method stub paint.setAntiAlias(true true); true //绘制直线 paint.setColor(Color.GREEN); //设置线条粗细 paint.setStrokeWidth(12); canvas.drawLine(120,40,170,90, paint); canvas.drawLine(320,90,370,40, paint); } }
//DrawCircle.java packagecom.scgm.android.drawable; package
importandroid.graphics.Canvas; import import android.graphics.Color; import android.graphics.Paint; importandroid.graphics.RectF; import
publicclassDrawCircleimplements drawGraphics{ implements publicclass null; private Paint paint=null null null; private Paint paint_eye=null null public DrawCircle(){ paint= new Paint(); paint_eye= new Paint(); }
@Override voiddraw(Canvas canvas) { public void // TODO TODOAuto-generated method stub //绘制圆形(圆心 x,圆心 y,半径 r,画笔 p) paint_eye.setAntiAlias(true true); true paint.setAntiAlias(true true); true RectF rectF = new newRectF(120,60,370,240); paint_eye.setColor(Color.WHITE); paint.setColor(Color.GREEN); canvas.drawCircle(190, 110, 18, paint_eye); canvas.drawCircle(300, 110, 18, paint_eye); canvas.drawArc(rectF, 180, 180,true paint); true, true } }
//GameStart.java
package com.scgm.android.drawable;
import android.app.Activity; importandroid.os.Bundle; import
publicclassGameStartextends Activity { extends publicclass null; private GameView mGameView=null null @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super this.mGameView= new newGameView(this this); this this setContentView(mGameView); } }
运行效果图: