前言
在上篇我们已经简单介绍了View游戏框架
的相关知识,大家有兴趣的话,可以参考
游编(1)—View游戏框架
那么今天就让我们来介绍下另一个游戏框架——SurfaceView
今天涉及的内容有:
- SurfaceView简介
- 继承SurfaceView实现一个初步的自定义View
- SurfaceView绘图后的刷屏方式
- 项目结果图
- 优化后的MySurfaceView源码
先来波效果图


一. SurfaceView简介
SurfaceView继承自View
,具备View
的所有特性。当我们要用SurfaceView
来绘制游戏界面的话,我们需要写自定义类(以MySurfaceView
为例)来继承SurfaceView
。SurfaceView
的界面绘制及声明周期等是由SurfaceHolder
来控制。然后SurfaceView
的绘制方法也不是用View
的onDraw()
方法了,而是需要些一个自己的绘制方法。我们一般将自定义的界面绘制方法放到SurfaceView
声明周期的创建阶段执行。在自定义的绘制方法中,我们需要在绘制之前,用SurfaceHolder
实例来锁住画布(锁住是为了防止多线程绘制导致画布显示混乱),然后执行绘制过程,等绘制结束后,又需要用SurfaceHolder
实例来解锁画布。
二.继承SurfaceView实现一个初步的自定义View
基于以上SurfaceView
的基本知识,然后重写View
的onTouchEvent(MotionEvent event)
方法拾取屏幕坐标点,让我们实现一个随着屏幕坐标移动的文字功能,则该自定义SurfaceView
类MySurfaceView
代码如下:
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private Context mContext;
private SurfaceHolder mSurfaceHolder;//用于控制SurfaceView
private Paint mPaint;
private float mX=100f;
private float mY=100f;
public MySurfaceView(Context context) {
super(context,null);
this.mContext=context;
//初始化SurfaceHolder
mSurfaceHolder=this.getHolder();
mSurfaceHolder.addCallback(this);
//初始化画笔
mPaint=new Paint();
mPaint.setStyle(Paint.Style.FILL);
mPaint.setTextSize(50f);
mPaint.setColor(Color.GREEN);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
//创建SurfaceView,绘制文字
myDraw();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
//SurfaceView改变的监听
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//SurfaceView销毁
}
/**自定义绘制**/
private void myDraw(){
LogUtil.i("=======myDraw=========");
//锁住画布
Canvas canvas=mSurfaceHolder.lockCanvas();
//开始绘制
canvas.drawText("Text Game",mX,mY,mPaint);
//释放画布
mSurfaceHolder.unlockCanvasAndPost(canvas);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mX=event.getX();
mY=event.getY();
//重新绘制
myDraw();
//此处一定要返回true
return true;
}
}
然后在TempActivity
中调用MySurfaceView
,代码如下:
public class TempActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState){
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
setContentView(new MySurfaceView(TempActivity.this));
}
}
运行效果图如下:

这里发现,随着手指移动,在绘制文字的时候,留下很多轨迹。于是边涉及到
SurfaceView
绘制后刷新的问题。
三.SurfaceView绘图后的刷屏方式
刷屏一般是在绘制逻辑之前执行,SurfaceView
的通用刷屏方式有4种。
- 绘制一个画布大小的rect覆盖到canvas上
- 重绘前在画布上填充一种颜色
- 重绘前在画布上用RGB绘制画布
- 每次绘制之前,绘制一张屏幕大小的图片覆盖到画布上
基于以上几种方式的话,我们优化了MySurfaceView
代码,下面看看执行了刷屏代码的最终实现效果:

此时便实现了跟随手指滑动的文字效果。
四. 项目结果图
下面是项目结构图

五, 优化后的MySurfaceView源码
下面贴出优化后的MySurfaceView
代码:
网友评论