当需要开发复杂的游戏,而且对程序的执行效率要求很高的时候,View类就不能满足要求了,这个时候必须使用【SurfaceView】类进行开发。例如,对速度要求很高的游戏,可以使用【双缓冲】来显示。游戏中的人物,背景,动画等都需要绘制在一个画布【Canvas】上。而SurfaceView可以直接访问一个画布,SurfaceView是提供给需要直接画像素而不是使用窗体部件的应用使用的。Android图形系统中的一个重要概念是Surface, View及其子类(如TextView,Button等)要画在Surface上。每个Surface创建一个Canvas对象(但是属性时常改变)来管理View在Surface上的绘图操作。
在使用SurceView开发时要注意的是,使用它绘图时,一般都是出现在【最顶层】。使用时还需要对其进行创建,销毁,情况改变时进行监视,这就要实现【SurfaceHolder.Callback】接口,如果要对被绘制的画布进行裁剪,控制其大小时都需要使用SurfaceHolder来完成处理。在程序中,SurfaceHolder对象需要通过getHolder方法获得,同时还需要addCallback方法来添加"回调函数"。
SurfaceView和View的明显不同就是SurfaceView不需要通过线程来更新视图,但是在绘制之前必须使用lockCanvas方法来锁定画布,并得到画布,然后在画布上绘制;当绘制完成后,使用unlockCanvasAndPost方法来解锁画布,于是才能显示在屏幕上。SurfaceView类的事件处理则和View一样,不再重复。
下面用代码来实现SurfaceView的简单应用:
package com.czz.test;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class KeyDownActivity extends Activity {
private static final int REFRESH = 0x00001;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
GameSurfaceView mGameSurfaceView = new GameSurfaceView(this);
this.setContentView(mGameSurfaceView);
new Thread(mGameSurfaceView).start();
}
public class GameSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
int iCount;
boolean mLoop;
SurfaceHolder mSurfaceHolder;
public GameSurfaceView(Context context) {
super(context);
// TODO Auto-generated constructor stub
mSurfaceHolder = this.getHolder();
//添加回调
mSurfaceHolder.addCallback(this);
this.setFocusable(true);
mLoop = true;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
new Thread(this).start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
mLoop = false;
}
@Override
public void run() {
// TODO Auto-generated method stub
// while(mLoop){
try{
Thread.sleep(500);
} catch(Exception e){
}
synchronized(mSurfaceHolder){
Draw();
}
// }
}
private void Draw(){
//锁定画布,得到canvas
Canvas canvas = mSurfaceHolder.lockCanvas();
if(mSurfaceHolder == null || canvas == null){
return;
}
if(iCount < 100){
iCount++;
} else {
iCount = 0;
}
Paint mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.BLACK);
//画个背景
canvas.drawRect(0, 0, 480, 800, mPaint);
switch(iCount % 4){
case 0:mPaint.setColor(Color.RED);break;
case 1:mPaint.setColor(Color.GREEN);break;
case 2:mPaint.setColor(Color.BLUE);break;
case 3:mPaint.setColor(Color.YELLOW);break;
default:mPaint.setColor(Color.WHITE);break;
}
canvas.drawOval(new RectF((480-30)/2-60, 100-80, (480-30)/2+60, 100+80), mPaint);
mPaint.setColor(Color.YELLOW);
canvas.drawCircle((480-30)/2, 100, 60, mPaint);
//设置裁剪区域
canvas.clipRect(0, 0, 240, 400);
//锁定画布
canvas.save();
canvas.rotate(45.0f);
canvas.drawRect(100, 300, 180, 330, mPaint);
//解除锁定
canvas.restore();
canvas.drawRect(10, 500, 50, 600, mPaint);
//绘制后解锁,才能显示
mSurfaceHolder.unlockCanvasAndPost(canvas);
}
}
}