Android 游戏开发之 SurfaceView


当我们从事复杂的图像绘制或者对程序的执行效率要求比较高的时候,我们会发现View是不能满足需求的。View是widget框架下的一个直接拖拉的控件产物。例如我们需要使用双缓冲来显示,直接访问画布canvas.这些都导致了我们需要比View更加强大的SurfaceView的出现。

在使用SurfaceView的时候我们需要注意的是,使用他们绘图的时候,一般都是出现在最顶层的。使用时需要对其进行创建、销毁、情况改变时进行监视,这个需要实现SurfaceHolder.Callback接口。如果要对被绘制的画布进行裁剪,控制其大小时都需要用SurfaceHolder来完成处理。

在SurfaceView的派生类中,使用getHolder方法来获取SurfaceHolder对象。同时还需要addCallback方法来添加回调函数。

surfaceChanged :在surfaceview的大小发生改变的时候调用。

surfaceCreated  : 在创建Surface时激发。

surfacedestroyed:在销毁Surface时激发。

addCallback:给SurfaceView添加一个回调函数。

lockCanvas :锁定画布。绘图之前必须锁定画布才能够得到画布对象。

unlockCanvasAndPost:开始绘制时锁定了画布,绘制完成之后解锁画布。

removeCallback:从SurfaceView中移除回调函数。

SurfaceView不同于View之处在于,SurfaceView不需要通过线程来更新视图,但是再绘制前需要使用lockCanvas锁定画布,并且得到画布,然后在画布上绘制你需要的图像。绘制完成之后需要使用lockCanvasAndPost方法来解锁画布。于是才能显示在屏幕之上。事件的处理规则和View是一样的。

下面我们来再屏幕闪显示一组图片,来做个Demo.

package com.rocky.example;
import Android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.ViewGroup.LayoutParams;
public class RockySurfaceView extends Activity {
 
 public final int WM_INVALIDATE=1;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.main);
   
        MySurfaceView myView=new MySurfaceView(this);
        LayoutParams lp=new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT);
        this.setContentView(myView, lp);
               
    }
}
package com.rocky.example;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback,Runnable{
 SurfaceHolder mSurfaceHolder;
 
 int index=0;
 boolean mLoop=false;
 
 int[] Image =new int[]
                  {
      R.drawable.image1,
      R.drawable.image2,
      R.drawable.image3,
      R.drawable.image4,
      R.drawable.image5,
      R.drawable.image6,
      R.drawable.image7,
      R.drawable.image8,
      R.drawable.image9,
      R.drawable.image10,
      R.drawable.image11,
      R.drawable.image12,
      R.drawable.image13,
      R.drawable.image14,
      R.drawable.image15,
      R.drawable.image16,
      R.drawable.image17,
      R.drawable.image18
                  };
 
 public MySurfaceView(Context context) {
  super(context);
  // TODO Auto-generated constructor stub
  mSurfaceHolder=this.getHolder();
  mSurfaceHolder.addCallback(this);
  this.requestFocus();
  mLoop=true;
 }
 @Override
 public void surfaceChanged(SurfaceHolder holder, int format, int width,
   int height) {
  // TODO Auto-generated method stub
  
 }

 @Override
 public void surfaceCreated(SurfaceHolder holder) {
  // TODO Auto-generated method stub
  
  new Thread(this).start();
 }
 @Override
 public void surfaceDestroyed(SurfaceHolder holder) {
  // TODO Auto-generated method stub
  
  mLoop=false;
 }
 private void draw()
 {
  Canvas canvas=mSurfaceHolder.lockCanvas();
  
  if(mSurfaceHolder==null||canvas==null)
  {
   return;
  }
  
  
  if(index<Image.length-1)
  {
   index++;
  }
  else
  {
   index=0;
  }
  
  //Paint mPaint=new Paint();
  //mPaint.setAntiAlias(true);
  ///mPaint.setColor(Color.BLACK);
  //canvas.drawRect(0,0,320,480, mPaint);
  canvas.drawBitmap(((BitmapDrawable)this.getResources().getDrawable(Image[index])).getBitmap(), 0,0,null);   
  mSurfaceHolder.unlockCanvasAndPost(canvas);
  
  
 }
 @Override
 public void run() {
  // TODO Auto-generated method stub
  
  while(mLoop)
  {
   try
   {
    Thread.sleep(200);
   }
   catch(Exception e)
   {
    
   }
   synchronized (mSurfaceHolder) {
    
    draw();
   }
  }
 }
 
 
 
 
}

这里只是简单的记录使用方法。Android的API实在太多了。

相关内容