72

我有一个简单的程序,可以将预览绘制CameraSurfaceView. 我正在尝试使用该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);
 }
}
4

3 回答 3

88

SurfaceViewView在这方面可能不像普通人那样工作。

相反,请执行以下操作:

  1. 将您的SurfaceView内部 FrameLayoutRelativeLayout布局 XML 文件中,因为这两者都允许在 Z 轴上堆叠小部件
  2. 将您的绘图逻辑移动到一个单独的自定义View类中
  3. 将自定义 View 类的实例作为FrameLayoutor 的子级添加到布局 XML 文件中RelativeLayout,但让它出现在SurfaceView

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

于 2010-05-29T11:11:58.237 回答
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");
}

invalidate并从以下位置调用onTouchEvent

public boolean onTouch(View v, MotionEvent event) {

    invalidate();
    return true;
}
于 2013-05-16T15:04:35.380 回答
1

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

于 2011-09-20T08:04:46.653 回答