如何在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方法中做任何事情。