如何在Android上使用Camera的SurfaceView上绘制叠加层?

时间:2010-05-29 05:05:24

标签: android camera surfaceview

我有一个简单的程序,可以将Camera的预览绘制成SurfaceView。我要做的是使用onPreviewFrame方法,每次将新帧绘制到SurfaceView时调用该方法,以便执行应该使用的invalidate方法调用onDraw方法。实际上,正在调用onDraw方法,但没有打印任何内容(我猜相机预览会覆盖我正在尝试绘制的文本)。

这是我拥有的SurfaceView子类的简化版本:

public class Superficie extends SurfaceView implements SurfaceHolder.Callback {
 SurfaceHolder mHolder;
 public Camera camera;
 Superficie(Context context) {
  super(context);
  mHolder = getHolder();
  mHolder.addCallback(this);
  mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
 }
 public void surfaceCreated(final SurfaceHolder holder) {
  camera = Camera.open();
  try {
   camera.setPreviewDisplay(holder);
   camera.setPreviewCallback(new PreviewCallback() {
    public void onPreviewFrame(byte[] data, Camera arg1) {
     invalidar();
    }
   });
  } catch (IOException e) {}
 }
 public void invalidar(){
  invalidate();
 }
 public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
  Camera.Parameters parameters = camera.getParameters();
  parameters.setPreviewSize(w, h);
  camera.setParameters(parameters);
  camera.startPreview();
 }
 @Override
 public void draw(Canvas canvas) {
  super.draw(canvas);
  // nothing gets drawn :(
  Paint p = new Paint(Color.RED);
  canvas.drawText("PREVIEW", canvas.getWidth() / 2,
    canvas.getHeight() / 2, p);
 }
}

3 个答案:

答案 0 :(得分:84)

在这方面,

SurfaceView可能不像常规View那样有效。

相反,请执行以下操作:

  1. 将您的SurfaceView放入 FrameLayoutRelativeLayout in 你的布局XML文件,因为两者都有 那些允许堆叠小部件 Z轴
  2. 移动绘图逻辑 进入单独的自定义View
  3. 添加自定义视图的实例 将布局XML文件作为一个类 FrameLayout或。{的孩子 RelativeLayout,但有它出现 在SurfaceView
  4. 之后

    这会导致您的自定义View课程浮动在SurfaceView之上。

    See here for a sample project将用于视频播放的SurfaceView上方的图层弹出面板分层。

答案 1 :(得分:17)

尝试从setWillNotDraw(false)致电surfaceCreated

public void surfaceCreated(SurfaceHolder holder) {
    try {
        setWillNotDraw(false); 
        mycam.setPreviewDisplay(holder);
        mycam.startPreview();
    } catch (Exception e) {
        e.printStackTrace();
        Log.d(TAG,"Surface not created");
    }
}

@Override
protected void onDraw(Canvas canvas) {

    canvas.drawRect(area, rectanglePaint);
    Log.w(this.getClass().getName(), "On Draw Called");
}

并从invalidate致电onTouchEvent

public boolean onTouch(View v, MotionEvent event) {

    invalidate();
    return true;
}

答案 2 :(得分:1)

我认为在SurfaceView的draw方法中执行任何操作之前,应先调用super.draw()方法。