1. SurfaceView 的概念和用途
    surfaceview是view的一个子类,可以直接从内存或者DMA等硬件接口中取得图像数据,是一个非常重要的绘图视图。他的特性是:可以在主线程之外的线程中向屏幕绘图,这样可以避免画图任务繁重的时候造成的主线程阻塞,从而提高了程序的反应速度。在游戏开发过程中多用到SurfaceView,游戏中的背景、人物、动画等等在画布canvas中画出。
  2. Surfaceview的实现和方法

1.实现步骤

        a.继承SurfaceView

        b.实现SurfaceHolder.Callback 接口

2.需要重写的方法

//在surface的大小发生改变时激发
public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){}
//在创建时触发,一般在这里调用画图的线程
public void surfaceCreated(SurfaceHolder holder){}
//在销毁时激发,一般在这里将画图的线程停止、释放。
public void surfaceDestroyed(SurfaceHolder holder) {}
//在surface的大小发生改变时激发
public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){}
//在创建时触发,一般在这里调用画图的线程
public void surfaceCreated(SurfaceHolder holder){}
//在销毁时激发,一般在这里将画图的线程停止、释放。
public void surfaceDestroyed(SurfaceHolder holder) {}

   在整个过程中:继承SurfaceView并实现SurfaceHolder.Callback接口---->SurfaceView.getHolder()获得SerfaceHolder对象  ----->然后SurfaceHolder.addCallback(callback) 添加回调函数  ----->SurfaceHolder.lockCanvas() 获得Canvas对象并锁定画布   ---->canvas绘画  -----》 surfaceHolder。unlockCanvasAndPost(Canvas canvas)结束锁定画图,并提交改变,将图形显示。


3.SurfaceHolder方法

SurfaceHolder,surface的控制器,用来操纵surface。处理它的Canvas上画的效果和动画,控制表面,大小,像素等。

要注意的几个方法:

(1)、abstract void addCallback(SurfaceHolder.Callback callback);
// 给SurfaceView当前的持有者一个回调对象。
(2)、abstract Canvas lockCanvas();
// 锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。
(3)、abstract Canvas lockCanvas(Rect dirty);
// 锁定画布的某个区域进行画图等..因为画完图后,会调用下面的unlockCanvasAndPost来改变显示内容。
// 相对部分内存要求比较高的游戏来说,可以不用重画dirty外的其它区域的像素,可以提高速度。
(4)、abstract void unlockCanvasAndPost(Canvas canvas);
// 结束锁定画图,并提交改变。
(1)、abstract void addCallback(SurfaceHolder.Callback callback);
// 给SurfaceView当前的持有者一个回调对象。
(2)、abstract Canvas lockCanvas();
// 锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。
(3)、abstract Canvas lockCanvas(Rect dirty);
// 锁定画布的某个区域进行画图等..因为画完图后,会调用下面的unlockCanvasAndPost来改变显示内容。
// 相对部分内存要求比较高的游戏来说,可以不用重画dirty外的其它区域的像素,可以提高速度。
(4)、abstract void unlockCanvasAndPost(Canvas canvas);
// 结束锁定画图,并提交改变。

三、通过自定义的SurfaceView组件实现的一个绘图类

package com.example.mydrawingboard;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Path;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;


public class MyView extends SurfaceView implements SurfaceHolder.Callback,OnTouchListener
{
	
	Paint paint=new Paint();  //创建一个画笔
	Path path=new Path();     //创建一个保存路径
	
	//由于我们这是自定义控件,所以要使用有两个参数的构造函数
	public MyView(Context context, AttributeSet attrs)
	{
		super(context, attrs);
		// TODO Auto-generated constructor stub
		getHolder().addCallback(this);  //添加一个回调函数
		paint.setTextSize(15);
		paint.setColor(Color.GREEN);
		paint.setStyle(Style.STROKE); //定义为空心
		setOnTouchListener(this);
	}
	//创建一个绘图方法
	public void draw(){
		//创建一个画布并且锁定画布
		Canvas canvas=getHolder().lockCanvas();
		canvas.drawColor(Color.WHITE);
		canvas.drawPath(path, paint);
		//画布抗锯齿
		canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG));
		//在整个绘图结束之后调用解锁画图
		getHolder().unlockCanvasAndPost(canvas);
	}
	
	public void clear(){
		path.reset();
		draw();
	}
	
	@Override
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3)
	{
		// TODO Auto-generated method stub
		
	}

	@Override
	public void surfaceCreated(SurfaceHolder arg0)
	{
		//在surface开始的时候就开始执行draw
		draw();
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder arg0)
	{
		// TODO Auto-generated method stub
		
	}
	@Override
	public boolean onTouch(View arg0, MotionEvent arg1)
	{
		// TODO Auto-generated method stub
		switch (arg1.getAction())
		{
		case MotionEvent.ACTION_DOWN:
			path.moveTo(arg1.getX(),arg1.getY());
			draw();
			break;

		case MotionEvent.ACTION_MOVE:
			path.lineTo(arg1.getX(),arg1.getY());
			draw();
			break;
		}
		//如果返回false,则只能执行down操作;
		return true;
	}

}
package com.example.mydrawingboard;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Path;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;


public class MyView extends SurfaceView implements SurfaceHolder.Callback,OnTouchListener
{
	
	Paint paint=new Paint();  //创建一个画笔
	Path path=new Path();     //创建一个保存路径
	
	//由于我们这是自定义控件,所以要使用有两个参数的构造函数
	public MyView(Context context, AttributeSet attrs)
	{
		super(context, attrs);
		// TODO Auto-generated constructor stub
		getHolder().addCallback(this);  //添加一个回调函数
		paint.setTextSize(15);
		paint.setColor(Color.GREEN);
		paint.setStyle(Style.STROKE); //定义为空心
		setOnTouchListener(this);
	}
	//创建一个绘图方法
	public void draw(){
		//创建一个画布并且锁定画布
		Canvas canvas=getHolder().lockCanvas();
		canvas.drawColor(Color.WHITE);
		canvas.drawPath(path, paint);
		//画布抗锯齿
		canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG));
		//在整个绘图结束之后调用解锁画图
		getHolder().unlockCanvasAndPost(canvas);
	}
	
	public void clear(){
		path.reset();
		draw();
	}
	
	@Override
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3)
	{
		// TODO Auto-generated method stub
		
	}

	@Override
	public void surfaceCreated(SurfaceHolder arg0)
	{
		//在surface开始的时候就开始执行draw
		draw();
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder arg0)
	{
		// TODO Auto-generated method stub
		
	}
	@Override
	public boolean onTouch(View arg0, MotionEvent arg1)
	{
		// TODO Auto-generated method stub
		switch (arg1.getAction())
		{
		case MotionEvent.ACTION_DOWN:
			path.moveTo(arg1.getX(),arg1.getY());
			draw();
			break;

		case MotionEvent.ACTION_MOVE:
			path.lineTo(arg1.getX(),arg1.getY());
			draw();
			break;
		}
		//如果返回false,则只能执行down操作;
		return true;
	}

}