Android开发:SurfaceView上新建线程绘制旋转图片 及 刷新特定区域(脏矩形)

何为脏矩形?比如surfaceview上绘制旋转图片的时候,只刷新一个特定的矩形区域就可以了。这个矩形区域就是脏矩形。在surfaceview上  canvas = holder.lockCanvas(new Rect(0, 0, 130, 130)); //获取画布 像这种带rect参数的就是脏矩形的刷新。

请看源码:

package yan.guoqi.rectphoto;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class DrawSurfaceView extends SurfaceView implements SurfaceHolder.Callback{

	private static final String tag2 = "DrawSV";
	private boolean runFlag = true;
	protected SurfaceHolder holder;
	private Bitmap rotateImg;
	private Thread myThread;
	
	public DrawSurfaceView(Context context, AttributeSet attrs)
	//构造函数
	{
		super(context, attrs);
		// TODO Auto-generated constructor stub
		rotateImg = BitmapFactory.decodeResource(getResources(), R.drawable.rotate_circle);
		rotateImg = Bitmap.createScaledBitmap(rotateImg, 100, 100, true);
		holder = this.getHolder();
		holder.addCallback(this);
		holder.setFormat(PixelFormat.TRANSPARENT);  //顶层绘制SurfaceView设成透明
		this.setZOrderOnTop(true);
		myThread = new Thread(new MyThread());
	}

	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
		// TODO Auto-generated method stub
		Log.v(tag2, "DrawSV:surfaceChanged...");
		
	}

	public void surfaceCreated(SurfaceHolder arg0) {
		// TODO Auto-generated method stub
		Log.v(tag2, "DrawSV:surfaceCreated...");
		//启动自定义线程		
		myThread.start();
		
	}

	public void surfaceDestroyed(SurfaceHolder arg0) {
		// TODO Auto-generated method stub
		Log.v(tag2, "DrawSV:surfaceDestroyed...");

		//终止自定义线程
		runFlag = false;
		myThread.interrupt();
		
	}
	
	/*自定义线程*/
	class MyThread implements Runnable{

		public void run() {
			// TODO Auto-generated method stub			
			Canvas canvas = null;
			int rotate = 0;
			while(runFlag){
				try {
					canvas = holder.lockCanvas(new Rect(0, 0, 130, 130)); //获取画布
					Paint paint = new Paint();
					//canvas.drawBitmap(rotateImg, 0, 0, paint); //绘制旋转的背景
					//创建矩阵控制图片旋转和平移
					Matrix matrix = new Matrix();
					//设置旋转角度
					matrix.postRotate((rotate += 48) % 360,
							rotateImg.getWidth() / 2, rotateImg.getHeight() / 2);
					//设置左边距和上边距
					matrix.postTranslate(0, 0);
					//绘制旋转图片
					canvas.drawBitmap(rotateImg, matrix, paint);
					//休眠控制最大帧率为每秒3绘制30次
					Thread.sleep(30);
					
					holder.unlockCanvasAndPost(canvas);//解锁画布,提交画好的图像
				} catch (Exception e) {
					// TODO: handle exception
					Log.v(tag2, "DrawSurfaceView:绘制失败...");
				}	
				
				
				
			}
			
		}
		
	}

}
需要注意的几点:

第一,就是如何安全中止一个线程。这里通过设置标志位来实现。因为自带的stop()方法不安全,android本身都不推荐。关于如何安全中止线程可以参考这里:http://www.iteye.com/problems/67052 http://www.dewen.org/q/1957

第二,holder.unlockCanvasAndPost(canvas);//解锁画布,提交画好的图像 这句话必须和                    canvas = holder.lockCanvas(new Rect(0, 0, 130, 130)); //获取画布  在一个{ }里。像这里的http://www.cnblogs.com/jqyp/archive/2012/01/01/2309692.html的做法在程序退出时会抛出异常。原因是线程中止的时候无法再解锁画布了。

第三,利用Matrix让图片旋转的核心代码:

//创建矩阵控制图片旋转和平移
					Matrix matrix = new Matrix();
					//设置旋转角度
					matrix.postRotate((rotate += 48) % 360,
							rotateImg.getWidth() / 2, rotateImg.getHeight() / 2);
					//设置左边距和上边距
					matrix.postTranslate(0, 0);
					//绘制旋转图片
					canvas.drawBitmap(rotateImg, matrix, paint);
					//休眠控制最大帧率为每秒3绘制30次
					Thread.sleep(30);

 第四,之所以将此surfaceview设成顶层透明,原因是杂家想探索在底层surfaceview预览摄像头视频的时候,在顶层的surfaceview绘制一个旋转的图片动画。但遗憾的是,图片确实是旋转了,底层的摄像头预览也正常。但就是旋转的图片将预览画面挡住了。唉,看来前文http://blog.csdn.net/yanzi1225627/article/details/8580034这里的360扫描二维码的界面不是通过这种思路实现的,抑或是 我旋转的图片不是透明的???  


你可能感兴趣的:(Android开发:SurfaceView上新建线程绘制旋转图片 及 刷新特定区域(脏矩形))