如何绘制覆盖的表面视图使用的照相机在 Android?

我有一个简单的程序,绘制预览的 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);
}
}
102810 次浏览

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

相反,应该这样做:

  1. 把你的 SurfaceView放在一个 进入 FrameLayoutRelativeLayout 您的布局 XML 文件,因为 那些允许小部件堆叠在 Z 轴
  2. 移动你的绘图逻辑 成为一个单独的自定义 View
  3. 添加自定义视图的实例 类添加到布局 XML 文件中,作为 FrameLayout的子女或 RelativeLayout,但让它出现 在 SurfaceView之后

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

我认为您应该先调用 super.draw()方法,然后再在 Surface View 的 Draw 方法中执行任何操作。

试试从 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;
}