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 stubrotateImg = 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 stubLog.v(tag2, "DrawSV:surfaceChanged...");}public void surfaceCreated(SurfaceHolder arg0) {// TODO Auto-generated method stubLog.v(tag2, "DrawSV:surfaceCreated...");//启动自定义线程myThread.start();}public void surfaceDestroyed(SurfaceHolder arg0) {// TODO Auto-generated method stubLog.v(tag2, "DrawSV:surfaceDestroyed...");//终止自定义线程runFlag = false;myThread.interrupt();}/*自定义线程*/class MyThread implements Runnable{public void run() {// TODO Auto-generated method stubCanvas 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 exceptionLog.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);