如何在 Android 上的相机使用的 SurfaceView 上绘制叠加层?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2933882/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to draw an overlay on a SurfaceView used by Camera on Android?
提问by Cristian
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).
我有一个简单的程序,可以将预览绘制Camera
到SurfaceView
. 我想要做的是使用该onPreviewFrame
方法,每次将新帧绘制到 中时都会调用该方法,SurfaceView
以便执行invalidate
应该调用该onDraw
方法的方法。事实上,onDraw
正在调用该方法,但没有打印任何内容(我猜相机预览覆盖了我试图绘制的文本)。
This is a simplify version of the SurfaceView
subclass I have:
这是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);
}
}
回答by CommonsWare
SurfaceView
probably does not work like a regular View
in this regard.
SurfaceView
View
在这方面可能不像常规那样工作。
Instead, do the following:
相反,请执行以下操作:
- Put your
SurfaceView
inside of aFrameLayout
orRelativeLayout
in your layout XML file, since both of those allow stacking of widgets on the Z-axis - Move your drawing logic
into a separate custom
View
class - Add an instance of the custom View
class to the layout XML file as a
child of the
FrameLayout
orRelativeLayout
, but have it appear after theSurfaceView
- 将您的
SurfaceView
内部 aFrameLayout
或RelativeLayout
放在您的布局 XML 文件中,因为这两个文件都允许在 Z 轴上堆叠小部件 - 将您的绘图逻辑移动到一个单独的自定义
View
类中 - 将自定义 View 类的实例作为
FrameLayout
or 的子项添加到布局 XML 文件中RelativeLayout
,但让它出现在SurfaceView
This will cause your custom View
class to appear to float above the SurfaceView
.
这将导致您的自定义View
类看起来漂浮在SurfaceView
.
See here for a sample projectthat layers popup panels above a SurfaceView
used for video playback.
请参阅此处的示例项目,该项目将弹出面板分层SurfaceView
用于视频播放。
回答by maximus
Try calling setWillNotDraw(false)
from surfaceCreated
:
尝试调用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");
}
and calling invalidate
from onTouchEvent
:
并invalidate
从onTouchEvent
:
public boolean onTouch(View v, MotionEvent event) {
invalidate();
return true;
}
回答by Devashish Kunal
I think you should call the super.draw()
method first before you do anything in surfaceView's draw method.
我认为您应该先调用该super.draw()
方法,然后再在 SurfaceView 的 draw 方法中执行任何操作。