当我们需要开发一个复杂游戏的时候,而且对程序的执行效率要求很高时,View类就不能满足需求了,这时必须用SurfaceView类进行开发。

例如,对速度要求很高的游戏时,View类就不能满足需求了,这时必须使用SurfaceView类进行开发。例如,对速度要求很高的游戏,可以使用双缓冲来显示。游戏中的背景、人物、动画等都需要绘制在一个画布(Canvas)上,而SurfaceView可以直接访问一个画布,SurfaceView 是提供给需要直接画像素而不是使用窗体部件的应用使用的。 每个Surface创建一个Canvas对象(但属性时常改变),用来管理View和Surface上的绘图操作。


具体示例:

Activity

public class Activity01 extends Activity {
	
	GameSurfaceView gameView = null;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       
        gameView = new GameSurfaceView(this);
        setContentView(gameView);
    }
}

GameSurfaceView

public class GameSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable{

	private Activity01 mActivity = null;
	
	private SurfaceHolder mHolder = null;
	private Thread mThread = null;;
	private boolean mLoop = false;
	
	private Canvas mCanvas = null;
	private Paint mPaint = null;
	private long drawStartTime = 0, drawCostTime = 0, drawTotalTime = 30;
	
	private float x, y;
	private int screenWidth = 480, screenHeight = 800;
	
	public GameSurfaceView(Context context) {
		super(context);

		mActivity = (Activity01)context;
		
		mHolder = this.getHolder();
		mHolder.addCallback(this);
		setFocusable(true);
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		mPaint = new Paint();
		mPaint.setColor(Color.CYAN);
		mLoop = true;
		
		new Thread(this).start();
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
		screenWidth = width;
		screenHeight = height;
		
		x = screenWidth / 2;
		y = screenHeight / 2;
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		mLoop = false;
	}

	@Override
	public void run() {
		while(mLoop){
			drawStartTime = SystemClock.uptimeMillis();
			
			synchronized (mHolder) {
				try {
					mCanvas = mHolder.lockCanvas();
					onDraw();		// repaint
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					if(mCanvas != null){
						mHolder.unlockCanvasAndPost(mCanvas);
					}
				}
			}
			
			drawCostTime = SystemClock.uptimeMillis() - drawStartTime;
			Log.i("drawCostTime", "drawCostTime = " + drawCostTime);
			try {
				if(drawCostTime < drawTotalTime){
					Thread.sleep(drawTotalTime - drawCostTime);		// sleep elapse time
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	private void onDraw(){
		if(mHolder == null && mPaint == null){
			return;
		}
		
		mPaint.setAntiAlias(true);
		mPaint.setAlpha(100);
		
		mPaint.setColor(Color.CYAN);	// paint background color
		mCanvas.drawRect(0, 0, screenWidth, screenHeight, mPaint);
		
		mPaint.setColor(Color.BLUE);	// paint foreground color
		mCanvas.drawCircle(x, y, 50, mPaint);
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		super.onTouchEvent(event);

		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			this.x = event.getX();
			this.y = event.getY();
			break;

		case MotionEvent.ACTION_MOVE:
			this.x = event.getX();
			this.y = event.getY();
			break;

		case MotionEvent.ACTION_UP:
			this.x = event.getX();
			this.y = event.getY();
			break;

		default:
			this.x = event.getX();
			this.y = event.getY();
			break;
		}

		return true;	// true then event can be implemented again
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event){
		super.onKeyDown(keyCode, event);
		
		if(keyCode == KeyEvent.ACTION_DOWN){
			this.mActivity.finish();
		}
		
		return true;
	}
}

运行效果:



源码下载