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

Cri*_*ian 69 camera android surfaceview

我有一个简单的程序,将预览绘制Camera成一个SurfaceView.我正在尝试做的是使用该onPreviewFrame方法,每次将新帧绘制到SurfaceViewinvalidate方法时调用该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);
 }
}
Run Code Online (Sandbox Code Playgroud)

Com*_*are 85

SurfaceViewView在这方面可能不像常规那样工作.

相反,请执行以下操作:

  1. 把你SurfaceView的内部 FrameLayoutRelativeLayout在布局XML文件,因为这两个都允许在Z轴部件堆叠
  2. 将绘图逻辑移动到单独的自定义View类中
  3. 将自定义View类的实例作为FrameLayoutor 的子项添加到布局XML文件中RelativeLayout,但将其显示在SurfaceView

这将导致您的自定义View类看起来浮动在SurfaceView.

请参阅此处,了解SurfaceView用于视频播放的上方弹出面板的示例项目.


max*_*mus 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");
}
Run Code Online (Sandbox Code Playgroud)

并要求invalidate来自onTouchEvent:

public boolean onTouch(View v, MotionEvent event) {

    invalidate();
    return true;
}
Run Code Online (Sandbox Code Playgroud)