SurfaceView是简单高效的用于渲染图形的类,适合用于简单的2D游戏开发。

本文介绍了Android中SurfaceView的使用,包括使用SurfaceView绘制单个图形,多个图形,组合图形,并使组合图形移动。

详细代码:github.com/Baolvlv/LearnAndroid/tree/master/SurfaceView

        surfaceView主要用于游戏开发,当view需要频繁绘制时,会消耗很多资源,这时可以使用surfaceview进行。同时surfaceviwe可以在主线程之外的线程中进行。当画面需要被动更新时(靠事件触发,例如棋牌类游戏),可以使用view,而需要主动更新时,则选择surfaceview

1.SurfaceView的使用

创建一个类继承自SurfaceViwe,并实现SurfaceHolder.Callback接口,实现构造函数与借口的三个方法

publicMyView(Context context) {

super(context);

//添加回调函数

getHolder().addCallback(this);

}

//surface创建时执行

@Override

public voidsurfaceCreated(SurfaceHolder holder) {

}

//surface改变时执行

@Override

public voidsurfaceChanged(SurfaceHolder holder, intformat, intwidth, intheight) {

}

//surface意外销毁时执行

@Override

public voidsurfaceDestroyed(SurfaceHolder holder) {

}

//创建画布,图形开始时锁定画布,图形结束后解锁画布

Canvas canvas = getHolder().lockCanvas();

getHolder().unlockCanvasAndPost(canvas);

2.SurfaceView绘制单个图形

声明化画笔,在构造方法中初始化并设置画笔颜色

//声明画笔

privatePaintpaint=null;

paint=newPaint();

paint.setColor(Color.RED);

在自定义的Draw方法中,设置画布颜色并绘制图形

public voiddraw(){

//创建画布,图形开始时锁定画布,图形结束后解锁画布

Canvas canvas = getHolder().lockCanvas();

//设置画布颜色

canvas.drawColor(Color.WHITE);

//绘制长100宽100的矩形

canvas.drawRect(0,0,100,100,paint);

getHolder().unlockCanvasAndPost(canvas);

}

在surfaceCreate方法中调用绘制方法

public voidsurfaceCreated(SurfaceHolder holder) {

draw();

}

在MainActivity的onCreate方法中添加View

setContentView(newMyView(this));

3.SurfaceView绘制多个图形

直接调用canvas不断绘制即可绘制多个图形

当需要对其中的一个图形进行旋转,剪切等变换时,canvas.save与canvas.restore配合使用,用以不影响其他图形,旋转是通过旋转画布实现

canvas.save();

canvas.rotate(90,getWidth()/2,getHeight()/2);

canvas.drawLine(0,getHeight()/2,getWidth(),getHeight(),paint);

//还原画布

canvas.restore();

4.SurfaceView绘制组合图形

绘制组合图形有三个要点:

1.需要一个抽象的容器类,其子类为各种具体的图形,同时包含List储存各种子类图形

2.画布在主SurfaceView中设置好后,在逐级容器间传递

3.每个类得到画布后,绘制自己的图形

步骤:

自定义Container类,设置用于储存的List并在构造函数中初始化

public classContanier {

//储存子容器的List

privateListchildren=null;

//构造函数,实例化list

publicContanier(){

children=newArrayList();

}

编写向list中添加与删除view方法

//添加子view方法

public voidaddChildernView(Contanier child){

children.add(child);

}

//移除子view方法

public voidremoveChidernView(Contanier child){

children.remove(child);

}

编写向子容器传递画布并绘制其独特图形的方法,之后在子容器中进行复写

//向子容器传递画布并且子容器完成自己的绘制

public voidchildernViewCanvasAndDraw(Canvas canvas){

}

编写向逐级子容器传递画布的方法

//将画布传递给子容器,同时为容器内list中所有的子容器设置画布

public voidsetCanvas(Canvas canvas){

childernViewCanvasAndDraw(canvas);

for(Contanier c :children){

c.setCanvas(canvas);

}

编写具体图形类,继承自Contanier,作为容器可嵌套,构造函数初始化画笔

public classRectextendsContanier{

privatePaintpaint=null;

//构造函数初始化画笔

publicRect(){

paint=newPaint();

paint.setColor(Color.RED);

}

重写父类方法,接收画布绘制图形

public voidchildernViewCanvasAndDraw(Canvas canvas){

super.childernViewCanvasAndDraw(canvas);

canvas.drawRect(0,0,100,100,paint);

}

主surfaceView构造函数中实例化contanier及具体图形

privateContaniercontanier;

privateRectrect;

privateCirclecircle;

contanier=newContanier();

rect=newRect();

circle=newCircle();

rect.addChildernView(circle);

contanier.addChildernView(rect);

设置画布,并调用contanier类的方法传递画布

//创建画布,图形开始时锁定画布,图形结束后解锁画布

Canvas canvas = getHolder().lockCanvas();

//设置画布颜色

canvas.drawColor(Color.WHITE);

//为所有容器统一设置画布

contanier.setCanvas(canvas);

getHolder().unlockCanvasAndPost(canvas);

5.使组合图形移动

通过x,y坐标完成移动,首先设置x,y坐标变量

//设置坐标

private floatx=0,y=0;

get和set方法

//get和set方法

public voidsetX(floatx) {

this.x= x;

}

public floatgetX() {

returnx;

}

public voidsetY(floaty) {

this.y= y;

}

public floatgetY() {

returny;

}

在contanier类中为子容器逐级设置画布的方法中进行移动

在canvas的save与restore方法中,进行画布移动

/通过save和restore进行移动变化

canvas.save();

//根据当前的x,y坐标移动画布

canvas.translate(getX(),getY());

childernViewCanvasAndDraw(canvas);

for(Contanier c :children){

c.setCanvas(canvas);

}

canvas.restore();

在最外层的矩形子类中,绘制图形后,当前纵坐标增加1,作为下一次绘制时的纵坐标,实现不断移动

//不断增加画布移动坐标

this.setY(getY() +1);

在主surfaceView中,设置timer与timerTask,进行不断绘制

//创建计时器与计时器任务对象

privateTimertimer=null;

privateTimerTasktask=null;

//开始计时器方法

public voidstartTimer(){

timer=newTimer();

task=newTimerTask() {

//实例化timertask,复写run方法,不断进行绘制

@Override

public voidrun() {

draw();

}

};

//timer执行timerTask,100毫米后开始,每100毫秒执行一次

timer.schedule(task,100,100);

}

//停止计时器

public voidstopTimer(){

//当计时器不为空时,取消计时器,并设置为空

if(timer!=null){

timer.cancel();

timer=null;

}

在surfaceCreate方法中,开始计时器,在surfaceDestoryed方法中,停止计时器,否则会引发异常

//surface创建时执行

@Override

public voidsurfaceCreated(SurfaceHolder holder) {

startTimer();

}

//surface意外销毁时执行

@Override

public voidsurfaceDestroyed(SurfaceHolder holder) {

//surface结束之后不停止timer,会出现异常

stopTimer();

}

更多相关文章

  1. Android中的OpenGL ES使用基础
  2. Android(安卓)Canvas绘图详解【转】
  3. 初学Android,图形图像之使用drawBitmapMesh扭曲图像(三十二)
  4. Android实现列表时间轴
  5. Android(安卓)自定义View探索——图片
  6. Android(安卓)Shape绘制实用圆圈
  7. Android中View绘制优化之一---- 优化布局层次
  8. Android(安卓)UI 优化指南
  9. Android下拉上滑显示与隐藏Toolbar另一种实现

随机推荐

  1. Android(安卓)错误信息捕获发送至服务器
  2. android jni中将大数据回调到java层的时
  3. 使用Ramdisk加速Android工程的编译 (Andro
  4. Android聊天列表Demo(QQ,微信,等通讯工具的
  5. Android(安卓)教程:如何刷入通讯基带
  6. 价格公道的 ViewSonic ViewPad 7e Androi
  7. 利用android_ndk开发OpenGLES如何利用上
  8. 作为一个Android开发者,你迷茫了吗?(内附1T
  9. 通过View.post()获取View的宽高引发的两
  10. android 微博登录与分享集成