如何在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那样工作。
相反,请执行以下操作:
- 把你的
SurfaceView放入你的布局XML文件的FrameLayout或者RelativeLayout中,因为这两个都允许在Z轴上堆叠小部件 - 将绘图逻辑移入单独的自定义
View类 - 将自定义View类的实例作为
FrameLayout或RelativeLayout的子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方法中做任何事情。