返回介绍

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

发布于 2025-02-26 12:46:18 字数 4261 浏览 0 评论 0 收藏 0

何为脏矩形?比如 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 扫描二维码的界面不是通过这种思路实现的,抑或是 我旋转的图片不是透明的??? **

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文