Android SurfaceView基础

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()");
	}
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值