如何在Android上的Camera上使用SurfaceView绘制覆盖图?

我有一个简单的程序,将Camera的预览画成SurfaceView 。 我想要做的是使用onPreviewFrame方法,每当一个新的框架被绘制到SurfaceView时被调用,以执行应该调用onDraw方法的invalidate方法。 实际上,正在调用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); } } 

SurfaceView在这方面可能不像常规View那样工作。

相反,请执行以下操作:

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

这将导致您的自定义View类在SurfaceView上浮动。

在这里看到一个示例项目 ,用于video播放的SurfaceView上方的popup面板层。

尝试从surfaceCreated调用setWillNotDraw(false)

 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"); } 

并从onTouchEvent调用invalidate

 public boolean onTouch(View v, MotionEvent event) { invalidate(); return true; } 

我想你应该先调用super.draw()方法,然后在surfaceView的draw方法中做任何事情。