View的缺点:

1. View缺乏双缓冲机制。

2. 更新View时必须更新View上显示的整个图片。

3. 新线程无法更新View组件。


Paint是在Canvas上绘制的,SurfaceView封装着一个Canvas,并且允许选取这个画布的一部分进行更新。SurfaceHolder封装着对SurfaceView的所有操作,例如返回画布,重写Canvas的事件回调函数(在Holder的callBack中)。


注意:

1. 在进行holder.unlockCanvasAndPost(canvas);时,解锁之前绘制的图形还处于缓冲之中---也就是会被下一次锁定画布后绘制的内容覆盖掉。避免的方法是再次锁定(有的甚至锁定了两次。)和解锁:

holder.lockCanvas(new Rect(0, 0, 0, 0));
holder.unlockCanvasAndPost(canvas);

原理:第二次绘制可能遮盖第一次,第三次可能遮盖第二次,但不可能遮盖第一次。

2.Canvas的save和restore方法

通常用于这样的情况:需要比如旋转画布后绘制一个图形,这以后绘制的图形不受这侧旋转的影响。这时就可以用save和restore。save来保存画布之前的状态,然后对画布进行旋转位移等操作。绘制图形后再restore恢复画布之前的状态。




public class MainActivity extends Activity {

// SurfaceHolder 负责维护SurfaceView上绘制的内容
private SurfaceHolder holder;
private Paint paint = new Paint();;

private String TAG = "SurfaceViewDemo";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView);

// 初始化SurfaceHolder对象。
holder = surfaceView.getHolder();
// 给SurfaceHolder添加一个回调对象
holder.addCallback(new SurfaceHolder.Callback() {

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
Log.i(TAG, "=== surfaceDestroyed ===");
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
Log.i(TAG, "=== surfaceCreated ===");

// 锁定整个surfaceView 返回的画布可以用来编辑上面的像素,并可以绘制Bitmap对象。
Canvas canvas = holder.lockCanvas();
// 绘制背景
Bitmap backBitmap = ((BitmapDrawable) getResources()
.getDrawable(R.drawable.img)).getBitmap();

canvas.drawBitmap(backBitmap, 0, 0, paint);
// 绘制完成,释放画布,提交修改
holder.unlockCanvasAndPost(canvas);
// 重新锁定一次
holder.lockCanvas(new Rect(0, 0, 0, 0));
holder.unlockCanvasAndPost(canvas);

}

@Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
// TODO Auto-generated method stub
Log.i(TAG, "=== surfaceChanged ===");
}
});

surfaceView.setOnTouchListener(new OnTouchListener() {

@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub

// 只处理按下事件
if (event.getAction() == MotionEvent.ACTION_DOWN) {
int cx = (int) event.getX();
int cy = (int) event.getY();

// 锁定SurfaceView局部区域,只更新局部内容以当前坐标为中心100边长的方形
// 参数 是左 上 右 下 点的坐标。
Canvas canvas = holder.lockCanvas(new Rect(cx - 50,
cy - 50, cx + 50, cy + 50));

// 保存当前Canvas的状态
canvas.save();
// 旋转画布
canvas.rotate(30, cx, cy);
paint.setColor(Color.RED);
canvas.drawRect(cx - 40, cy - 40, cx, cy, paint);
canvas.restore(); // restore之后画的图形将不受之前旋转30度的影响。
paint.setColor(Color.GREEN);
// 绘制绿色方块
canvas.drawRect(cx, cy, cx + 40, cy + 40, paint);
// 绘制完成释放画布
holder.unlockCanvasAndPost(canvas); //可以把下面代码注释掉比较效果
holder.lockCanvas(new Rect(0, 0, 0, 0));
holder.unlockCanvasAndPost(canvas);
holder.lockCanvas(new Rect(0, 0, 0, 0));
holder.unlockCanvasAndPost(canvas);
}
return false;
}
});
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

}