爱自在的专栏

Android = Linux内核层、硬件抽象层(HAL)、运行时库层(Runtime)、应用程序框架层(Application Framework)以及应用程序层(Application)...

Android SurfaceView SurfaceHoder 和 Canvas

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;
	}

}


 

 

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012587637/article/details/22875785
个人分类: Android
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭