如何在 Android 上的 Camera 使用的 SurfaceView 上绘制叠加层?

发布于 2024-09-04 03:50:36 字数 1434 浏览 2 评论 0原文

我有一个简单的程序,可以将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);
 }
}

I have a simple program that draws the preview of the Camera into a SurfaceView. What I'm trying to do is using the onPreviewFrame method, which is invoked each time a new frame is drawn into the SurfaceView, in order to execute the invalidate method which is supposed to invoke the onDraw method. In fact, the onDraw method is being invoked, but nothing there is being printed (I guess the camera preview is overwriting the text I'm trying to draw).

This is a simplify version of the SurfaceView subclass I have:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

吹泡泡o 2024-09-11 03:50:36

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

相反,请执行以下操作:

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

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

SurfaceView probably does not work like a regular View in this regard.

Instead, do the following:

  1. Put your SurfaceView inside of a
    FrameLayout or RelativeLayout in
    your layout XML file, since both of
    those allow stacking of widgets on
    the Z-axis
  2. Move your drawing logic
    into a separate custom View class
  3. Add an instance of the custom View
    class to the layout XML file as a
    child of the FrameLayout or
    RelativeLayout, but have it appear
    after the SurfaceView

This will cause your custom View class to appear to float above the SurfaceView.

无言温柔 2024-09-11 03:50:36

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

Try calling setWillNotDraw(false) from 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");
}

and calling invalidate from onTouchEvent:

public boolean onTouch(View v, MotionEvent event) {

    invalidate();
    return true;
}
瞎闹 2024-09-11 03:50:36

我认为在 SurfaceView 的绘制方法中执行任何操作之前,您应该先调用 super.draw() 方法。

I think you should call the super.draw() method first before you do anything in surfaceView's draw method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文