MySurfaceView
package org.wp.activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
/**
* SurfaceHolder.Callback 接口:
* 只要继承SurfaceView类并实现SurfaceHolder.Callback接口就可以实现一个自定义的SurfaceView了
* SurfaceHolder.Callback在底层的Surface状态发生变化的时候通知View,
* SurfaceHolder.Callback具有如下的接口:
* 1> surfaceCreated(SurfaceHolder holder):当Surface第一次创建后会立即调用该函数。
* 程序可以在该函数中做些和绘制界面相关的初始化工作,
* 一般情况下都是在另外的线程来绘制界面,
* 所以不要在这个函数中绘制Surface。
* 2> surfaceChanged(SurfaceHolder holder, int format, int width, int height):
* 当Surface的状态(大小和格式)发生变化的时候会调用该函数,
* 在surfaceCreated调用后该函数至少会被调用一次。
* 3> surfaceDestroyed(SurfaceHolder holder):当Surface销毁时会调用该函数
*
* SurfaceHolder 类:
* 它是一个用于控制surface的接口,它提供了控制surface的大小,格式,上面的像素,即监视其改变的。
* SurfaceView的getHolder()函数可以获取SurfaceHolder对象,Surface就在SurfaceHolder对象内。
* 虽然Surface保存了当前窗口的像素数据,但是在使用过程中是不直接和Surface打交道的,
* 由SurfaceHolder的Canvas lockCanvas()或则Canvas lockCanvas()函数来获取Canvas对象,
* 通过在Canvas上绘制内容来修改Surface中的数据。
*
* 如果Surface不可编辑或则尚未创建调用该函数会返回null,
* 在 unlockCanvas() 和 lockCanvas()中Surface的内容是不缓存的,
* 所以需要完全重绘Surface的内容,为了提高效率只重绘变化的部分
* 则可以调用lockCanvas(Rect rect)函数来指定一个rect区域,
* 这样该区域外的内容会缓存起来。
*
* 在调用lockCanvas函数获取Canvas后,SurfaceView会获取Surface的
* 一个同步锁直到调用unlockCanvasAndPost(Canvas canvas)函数才释放该锁,
* 这里的同步机制保证在Surface绘制过程中不会被改变(被摧毁、修改)。
*
* 我没有在该surfaceview的初始化函数中将其 ScreenW 与 ScreenH 进行赋值,
* 这里要特别注意,如果你在初始化调用ScreenW = this.getWidth(); 和 ScreenH = this.getHeight();
* 那么你将得到很失望的值 全部为0;原因是和接口Callback接口机制有关,
* 当我们继承callback接口会重写它的surfaceChanged()、surfaceCreated()、surfaceDestroyed(),
* 这几个函数当surfaceCreated()被执行的时候,真正的view才被创建,也就是说之前得到的值为0 ,
* 是因为初始化会在surfaceCreated()方法执行以前执行,view没有的时候我们去取屏幕宽高肯定是0,
* 所以这里要注意这一点;
* 这里我把draw的代码都try起来,主要是为了当画的内容中一旦抛出异常了,那么我们也能 在finally中执行该操作。
* 这样当代码抛出异常的时候不会导致Surface出去不一致的状态。
* 其实这就是一个简单的游戏架构了,当然还少了按键处理,声音播放等等。
*
* @author wp
*
*/
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
private static final String TAG = "MySurfaceView";
private SurfaceHolder sfh;
private Thread th;
private Paint paint;
private Canvas canvas;
private int ScreenW, ScreenH;
public MySurfaceView(Context context) {
super(context);
sfh = this.getHolder();
sfh.addCallback(this);
th = new Thread(this);
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
this.setKeepScreenOn(true);
}
/**
* 自己定义的draw()方法, 放在线程中不断调用的
*/
private void draw() {
try {
Log.i(TAG, "draw()");
canvas = sfh.lockCanvas(); // 得到一个canvas实例
canvas.drawColor(Color.WHITE); // 刷屏
canvas.drawText("MySurfaceView", 100, 100, paint); // 画文字文本
canvas.drawText("这是一个简单的游戏框架", 100, 160, paint);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (canvas != null)
sfh.unlockCanvasAndPost(canvas); // 将画好的画布提交
}
}
@Override
public void run() {
while (true) {
draw();
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.i(TAG, "surfaceCreated()");
ScreenW = this.getWidth();
ScreenH = this.getHeight();
Log.i(TAG, "ScreenW:" + ScreenW + " ScreenH:" + ScreenH);
th.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.i(TAG, "surfaceChanged()");
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.i(TAG, "surfaceDestroyed()");
}
}