1. SurfaceView
更新的速度特别快,可以直接从内存或者DMA等硬件接口中取得图像数据的绘图容器
可以在主线程之外的线程中向屏幕绘图上,可以避免绘图任务繁重导致主线程阻塞,从而提高程序的反应速度。在游戏开发中多用到SurfaceView,游戏中的背景、人物、动画等尽量在canvas绘制
2.SurfaceView 与View 的区别
SurfaceView 是在一个新的起的线程中绘制画面,而View必须在UI中绘制更新画面。可以理解为SurfaceView的更新不需要在主线程中进行,这样就可以避免主线程来做大量的界面更新操作,引起ANR(主线程的界面更新的消息队列中存在大量的更新界面请求)
实际开发中,高级UI和低级UI并用
3.SurfaceView的使用
- 继承SurfaceView并实现SurfaceHolder.Callback接口
所有绘图工作必须在Surface被创建之后才能爱上,而在Surface被销毁之前必须结束,所以Callback中的SurfaceCreated和SurfaceDestroyer就成了绘图处理代码的边界
Surface是显卡内存的映射
public class GameView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
- SurfaceHolder
SurfaceHolder 为surfaceView的控制器,用来操纵surface。处理他的Canvas上画的效果和动画,控制表面,大小,像素
注意点:
- 2.1 abstact void addCallback(SurfaceHolder.Callback callBack)
给SurfaceView 当前持有者一个回调事件,通过这个建立纽带
mSurfaceHolder = getHolder();
// 设置操作回调事件
mSurfaceHolder.addCallback(this);
- 2.2 abstractCanvas lockCanvas()
锁定画布,一般锁定后就可以通过其返回的画布对象Canvase,在其上面画图等操作
// 锁住画布才能绘图
mCanvas = mSurfaceHolder.lockCanvas();
mCanvas.drawRect(50, 50, 100, 100, mPaint);
- 2.3 abstract Canvas lockCanvas(Rect dirty)
锁定画布的某个区域进行画图等,因为画完图后,会调用下面的unlockCanvasAndPost来改变显示内容
相对部分内存要求比较高的游戏来说,可以不用重画dirty外的其他区域的像素,可以提高速度
- 2.4 abstract void unlockCanvasAndPost(Canvas canvas)
结束锁定画图,并提交改变
// 解锁并提交
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
4.SurfaceView的生命周期
在SurfaceView的派生类中,使用geHolder方法来获取SurfaceHolder对象,向addCallBack来添加回调函数
surfaceChanged:在surfaceView的大小发生改变的时候回调
surfaceCreated:在创建Surface时回调
surfaceDestroyed:在销毁Surface时激发
5.画一个方块
package com.su.botanywarzombies;
import com.su.botanywarzombies.view.GameView;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
private GameView mGameView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGameView = new GameView(this);
setContentView(mGameView);
}
}
GameView 的基本使用方法
package com.su.botanywarzombies.view;
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;
public class GameView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
public static final String TAG = GameView.class.getSimpleName();
private boolean gameRunFlag;
// 绘图画笔
private Paint mPaint;
// 绘图画布
private Canvas mCanvas;
private SurfaceHolder mSurfaceHolder;
public GameView(Context context) {
super(context);
gameRunFlag = true;
mPaint = new Paint();
mSurfaceHolder = getHolder();
// 设置操作回调事件
mSurfaceHolder.addCallback(this);
}
@Override
public void surfaceCreated(SurfaceHolder arg0) {
Log.d(TAG, "surfaceCreated");
new Thread(this).start();
}
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
}
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
Log.d(TAG, "surfaceDestroyed");
gameRunFlag = false;
}
@Override
public void run() {
while (gameRunFlag) {
// 这里需要考虑线程同步
synchronized (mSurfaceHolder) {
try {
// 锁住画布才能绘图
mCanvas = mSurfaceHolder.lockCanvas();
int color = mPaint.getColor();
mPaint.setColor(Color.RED);
mCanvas.drawRect(50, 50, 100, 100, mPaint);
// 好习惯画笔复位
mPaint.setColor(color);
} catch (Exception e) {
e.printStackTrace();
} finally {
// 解锁并提交
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
}
try {
// 视频达到24帧,1秒24帧图片,肉眼是感受不到变化
Thread.sleep(60);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}