Surface在SDK的文档中的描述是这样的:Handle onto a raw buffer that is being managed by the screen compositor,Android中的Surface就是一个用来画图形(graphics)或图像(image)的地方,对于View及其子类,都是画在Surface上,各Surface对象通过Surfaceflinger合成到frameBuffer,每个Surface都是双缓冲,它有一个backBuffer和一个frontBuffer,Surface中创建了Canvas对象,用来管理Surface绘图操作,Canvas对应Bitmap,存储Surface中的内容。流程为:
1:创建一个Bitmap对象。
2:创建一个Canvas对象关联创建的Bitmap对象。
3:在Canvas上进行绘制。
4:锁定Canvas画布。
5:将Bitmap内容绘制到backBuffer中去。
6:解锁Canvas画布。
二、SurfaceView
SurfaceView是视图类View的子类,且实现了Parcelable接口且实现了Parcelable接口,其中内嵌了一个专门用于绘制的Surface,SurfaceView可以控制这个Surface的格式和尺寸,以及Surface的绘制位置。可以理解为Surface就是管理数据的地方,SurfaceView就是展示数据的地方。
三、SurfaceHolder
SurfaceHolder是一个接口,类似于一个surace的监听器。通过下面三个回调方法监听Surface的创建、销毁或者改变。
SurfaceView中调用getHolder方法,可以获得当前SurfaceView中的surface对应的SurfaceHolder,SurfaceHolder中重要的方法有:
1: abstract void addCallback(SurfaceHolder.Callback callback ); 为SurfaceHolder添加一个SurfaceHolder.Callback回调接口。
2: abstract Canvas lockCanvas() ; 获取Surface中的Canvas对象,并锁定之。所得到的Canvas对象。
3:abstract void unlockCanvasAndPost(Canvas canvas); 当修改Surface中的数据完成后,释放同步锁,并提交改变,然后将新的数据进行展示。
四、SurfaceHolder.Callback
SurfaceHolder.Callback是SurfaceHolder接口内部的静态子接口,SurfaceHolder.Callback中定义了三个接口方法:
1:public void sufaceChanged(SurfaceHolder holder,int format,int width,int height){}//Surface的大小发生改变时调用。
2: public void surfaceCreated(SurfaceHolder holder){}//Surface创建时激发,一般在这里调用画面的线程。
3: public void surfaceDestroyed(SurfaceHolder holder){}//销毁时激发,一般在这里将画面的线程停止、释放。
SurfaceView和View最本质的区别在于:SurfaceView是在一个新起的单独线程中可以重新绘制画面而View必须在UI的主线程中更新画面。
下面通过一个丢西瓜的实例来理解:
Spirite.java
public class Spirite {
private Bitmap mImage;
private Matrix mMatrix = new Matrix();
private PointF mV = new PointF();
private Random mRan = new Random();
public Spirite(Bitmap image){
mImage = image;
mMatrix.setTranslate(0, 380);
mV.x = 10F;
mV.y = -40F;
}
public void initSpirite(){
switch(emitPos()){
case 0:
emitAtPos0();
break;
default:
emitAtPos1();
}
}
private void emitAtPos0(){
float x = - mImage.getWidth();
float y = 100 + mRan.nextInt(300);
mMatrix.setTranslate(x, y);
mV.x = 15+ mRan.nextInt(11);
mV.y = -25 - mRan.nextInt(6);
}
private void emitAtPos1(){
float x = 50 + mRan.nextInt(301);
float y = 480;
mMatrix.setTranslate(x, y);
mV.x = 10+ mRan.nextInt(11);
mV.y = -30 - mRan.nextInt(16);
}
//1、要用随机数决定抛射的位置
private int emitPos(){
return mRan.nextInt(2);
}
//用于计算移动
public void move(){
mMatrix.postTranslate(mV.x, mV.y);
//改变竖直方向的速度
mV.y += 2F;
}
//用于绘制到屏幕上
public void draw(Canvas canvas){
canvas.drawBitmap(mImage, mMatrix, null);
}
}
MySurfaceView.java
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback{
private SurfaceHolder mHolder;
private MyThread mThread = new MyThread();
public MySurfaceView(Context context) {
super(context);
// TODO Auto-generated constructor stub
mHolder = getHolder();
mHolder.addCallback(this);
}
//在缓冲区发生改变的时候调用
@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
Thread thread = new Thread(mThread);
thread.start();
}
//缓冲区销毁之前调用
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
mThread.stopThread();
}
//该方法用于将来计算物理效果
protected void stepOnce(){
}
//该方法用于绘制图形
protected void drawOnce(Canvas canvas){
}
//线程每运行一个循环,该方法就被调用一次
private void runOnce(){
stepOnce();
//通过mHolder获得对缓冲区的画布的访问
Canvas canvas = mHolder.lockCanvas();
drawOnce(canvas);
//通过mHolder,把绘制好的内容同步到屏幕上
mHolder.unlockCanvasAndPost(canvas);
}
class MyThread implements Runnable{
private boolean mIsRun = true;
@Override
public void run() {
// TODO Auto-generated method stub
while(mIsRun){
runOnce();
}
}
public void stopThread(){
mIsRun = false;
}
}
}
MyGameView.java 继承 MySurfaceView
public class MyGameView extends MySurfaceView {
private Drawable mBackground;
private Context mContext;
private Bitmap mBitmap;
private Spirite mSpirite;
private ArrayList<Spirite> mSpirites = new ArrayList<Spirite>();
private long mNextEmmitTime;
private Random mRan = new Random();
public MyGameView(Context context) {
super(context);
// TODO Auto-generated constructor stub
mContext = context;
initBackground();
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.watermellon);
mSpirite = new Spirite(mBitmap);
}
//计算下一次产生精灵的时间,定时产生精灵
private void emmitSpirite(){
long current = System.currentTimeMillis();
if(current-mNextEmmitTime>0){
Spirite spirite = new Spirite(mBitmap);
spirite.initSpirite();
mSpirites.add(spirite);
mNextEmmitTime = current + 200 + mRan.nextInt(1300);
}
}
//让精灵列表的每个精灵都移动
private void moveSpirites(){
for(int i = 0; i<mSpirites.size();i++){
Spirite spirite = mSpirites.get(i);
spirite.move();
}
}
//让精灵列表的每个精灵都画到画布上
private void drawSpirites(Canvas canvas){
for(int i = 0; i<mSpirites.size();i++){
Spirite spirite = mSpirites.get(i);
spirite.draw(canvas);
}
}
//初始化背景
private void initBackground(){
mBackground = mContext.getResources().getDrawable(R.drawable.background);
mBackground.setBounds(0,0,800,480);
}
@Override
protected void stepOnce() {
// TODO Auto-generated method stub
super.stepOnce();
emmitSpirite();
moveSpirites();
//mSpirite.move();
}
@Override
protected void drawOnce(Canvas canvas) {
// TODO Auto-generated method stub
super.drawOnce(canvas);
mBackground.draw(canvas);
drawSpirites(canvas);
//mSpirite.draw(canvas);
}
}
MySurfaceViewActivity.java
public class MySurfaceViewActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View view = new MyGameView(this);
setContentView(view);
}
}
附上demo下载地址: SurfaceView小例子