如何在Android上正确使用setZOrderMediaOverlay?
与许多其他人一样,我尝试在相机预览(使用 SurfaceView)上绘制 3D 对象(使用 GLSurfaceView),以及放置在顶部的一些按钮。我实际上得到了一个可以工作的原型,但是我无法让 onResume 正常工作。恢复后,GLSurfaceView 留在后面并且不再可见。我知道它正在工作,因为如果我从布局中删除 SurfaceView,我可以很好地看到绘图。
目标是 Nexus One,运行原生 2.3.3 ROM。
这是布局 xml: <代码>
<com.example.cameratest.GLPreview
android:id="@+id/cubes"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<com.example.cameratest.Preview
android:id="@+id/camera"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/buttongroup"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="right" android:gravity="center">
<Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:id="@+id/buttonClose"></Button>
<Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:id="@+id/buttonMode"></Button>
<Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:id="@+id/buttonCameraInfo"></Button>
</LinearLayout>
<代码>
所有这些都包含在
块中,但由于某种原因,我无法将其包含在上面的 列表中。
Preview
是扩展 SurfaceView
并实现相机预览逻辑的类。
当活动启动时,这效果很好。当我启动另一个活动(例如,按其中一个按钮)并完成该活动后,主活动将恢复,但 3D 对象不再可见。
我发现此讨论其中提到 setZOrderMediaOverlay()
将帮助解决此 z 排序问题。另外,setZOrderMediaOverlay()的Android文档说这个函数应该是称为“在表面视图的包含窗口附加到窗口管理器之前”。我不知道应该如何解释该语句,因此我将调试语句放入代码中以查看事件的顺序。 GLSurfaceView
代码如下所示:
public class GLPreview extends GLSurfaceView
{
private static final String TAG = "GLPreview";
public GLPreview(Context context, AttributeSet attrs)
{
super(context, attrs);
// this.setZOrderMediaOverlay(true);
}
public void onPause()
{
super.onPause();
Log.d(TAG, "GLPreview: OnPause");
}
public void onResume()
{
// this.setZOrderMediaOverlay(true);
super.onResume();
Log.d(TAG, "GLPreview: OnResume");
}
public void surfaceCreated(SurfaceHolder holder)
{
Log.d(TAG, "GLPreview: surfaceCreated");
super.surfaceCreated(holder);
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
{
Log.d(TAG, String.format("GLPreview: surfaceChanged, format=%d, w=%d, h=%d", format, w, h));
super.surfaceChanged(holder, format, w, h);
}
public void surfaceDestroyed(SurfaceHolder holder)
{
Log.d(TAG, "GLPreview: surfaceDestroyed");
super.surfaceDestroyed(holder);
}
protected void onAttachedToWindow()
{
Log.d(TAG, "GLPreview: onAttachedToWindow");
super.onAttachedToWindow();
}
protected void onDetachedFromWindow()
{
Log.d(TAG, "GLPreview: onDetachedFromWindow");
super.onDetachedFromWindow();
}
protected void onWindowVisibilityChanged (int vis)
{
String newVisibility;
switch (vis)
{
case View.GONE:
newVisibility = "GONE";
break;
case View.INVISIBLE:
newVisibility = "INVISIBLE";
break;
case View.VISIBLE:
newVisibility = "VISIBLE";
break;
default:
newVisibility = String.format("Unknown constant %d", vis);
}
Log.d(TAG, String.format("GLPreview: onWindowVisibilityChanged -> %s", newVisibility));
super.onWindowVisibilityChanged(vis);
}
}
这是我启动应用程序时的事件顺序:
GLPreview: OnResume GLPreview: onAttachedToWindow GLPreview: onWindowVisibilityChanged -> VISIBLE GLPreview: surfaceCreated GLPreview: surfaceChanged, format=1, w=800, h=480
因此,我假设需要在 onResume 中调用
或在构造函数中。但是,我在 setZOrderMediaOverlay()
()GLSurfaceView
或 中尝试了
类,但它们都没有帮助解决问题。setZOrderMediaOverlay()
与 true
或 false
的各种组合>SurfaceView
我对 Android 编程还比较陌生。我已经走了这么远,但此时我需要一些帮助。如果有人在这种情况下成功使用了 setZOrderMediaOverlay()
并使其与 onResume()
一起工作,请告诉我需要如何完成此操作。
预先非常感谢!
Like many others, I am trying to draw 3D objects (using GLSurfaceView) on camera preview (using SurfaceView), along with some buttons placed on top. I actually got a prototype working, but I could not get the onResume working correctly. After a resume, GLSurfaceView stays behind and is not visible anymore. I know that it is working, because I can see the drawing fine if I remove the SurfaceView from the layout.
The target is Nexus One, running stock 2.3.3 ROM.
Here's the layout xml:
<com.example.cameratest.GLPreview
android:id="@+id/cubes"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<com.example.cameratest.Preview
android:id="@+id/camera"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/buttongroup"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="right" android:gravity="center">
<Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:id="@+id/buttonClose"></Button>
<Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:id="@+id/buttonMode"></Button>
<Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:id="@+id/buttonCameraInfo"></Button>
</LinearLayout>
All of this is wrapped in a <merge>
block, but for some reason, I could not include it in the above <code>
listing. Preview
is the class that extends SurfaceView
and implements the camera preview logic.
This works fine when the activity launches. After I launch another activity (for example, by pressing one of the buttons) and finish that activity, the main activity resumes but the 3D objects are not visible anymore.
I found this discussion where it is mentioned that setZOrderMediaOverlay()
will help fix this z-ordering issue. Also, the Android document for setZOrderMediaOverlay() says this function should be called "before the surface view's containing window is attached to the window manager". I do not know how I should interpret that statement, so I put debug statements in the code to see the sequence of events. Here's how the GLSurfaceView
code looks like:
public class GLPreview extends GLSurfaceView
{
private static final String TAG = "GLPreview";
public GLPreview(Context context, AttributeSet attrs)
{
super(context, attrs);
// this.setZOrderMediaOverlay(true);
}
public void onPause()
{
super.onPause();
Log.d(TAG, "GLPreview: OnPause");
}
public void onResume()
{
// this.setZOrderMediaOverlay(true);
super.onResume();
Log.d(TAG, "GLPreview: OnResume");
}
public void surfaceCreated(SurfaceHolder holder)
{
Log.d(TAG, "GLPreview: surfaceCreated");
super.surfaceCreated(holder);
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
{
Log.d(TAG, String.format("GLPreview: surfaceChanged, format=%d, w=%d, h=%d", format, w, h));
super.surfaceChanged(holder, format, w, h);
}
public void surfaceDestroyed(SurfaceHolder holder)
{
Log.d(TAG, "GLPreview: surfaceDestroyed");
super.surfaceDestroyed(holder);
}
protected void onAttachedToWindow()
{
Log.d(TAG, "GLPreview: onAttachedToWindow");
super.onAttachedToWindow();
}
protected void onDetachedFromWindow()
{
Log.d(TAG, "GLPreview: onDetachedFromWindow");
super.onDetachedFromWindow();
}
protected void onWindowVisibilityChanged (int vis)
{
String newVisibility;
switch (vis)
{
case View.GONE:
newVisibility = "GONE";
break;
case View.INVISIBLE:
newVisibility = "INVISIBLE";
break;
case View.VISIBLE:
newVisibility = "VISIBLE";
break;
default:
newVisibility = String.format("Unknown constant %d", vis);
}
Log.d(TAG, String.format("GLPreview: onWindowVisibilityChanged -> %s", newVisibility));
super.onWindowVisibilityChanged(vis);
}
}
Here's the sequence of events when I start the application:
GLPreview: OnResume GLPreview: onAttachedToWindow GLPreview: onWindowVisibilityChanged -> VISIBLE GLPreview: surfaceCreated GLPreview: surfaceChanged, format=1, w=800, h=480
So I assumed that setZOrderMediaOverlay()
needs to be called in either onResume()
or in the constructor. However, I tried various combinations of setZOrderMediaOverlay()
with true
or false
, in the GLSurfaceView
or the SurfaceView
classes, but none of it helped with the problem.
I am relatively new when it comes to Android programming. I have come so far but at this point I need some help. If someone who used setZOrderMediaOverlay()
successfully in this scenario and got it working with onResume()
let me know how this needs to be done.
Thanks a lot in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我已经为同样的问题苦苦挣扎了一段时间,但相信下面的代码现在可以工作了。 (暂停/锁定后,无论相机打开还是关闭,它都会继续工作)。
首先,我没有在布局文件中定义任何视图等 - 它们是在代码中创建的。以下是从主 onCreate() 方法调用的 - 请注意 augScreen 上的 setZOrderMediaOverlay()。
除了将 onPause() 和 onResume() 传递到 augScreen 之外,我在 onPause() 或 onResume() 中没有做任何特别的事情。
I have struggled with the same issue for some time, but believe the code below now works. (It continues to work after pausing/ locking regardless of whether the camera is on or off).
Firstly, I haven't got any views etc defined in the layout file - they're created in code. The following is called from the main onCreate() method - Note the setZOrderMediaOverlay() on the augScreen.
I have done nothing special within onPause() or onResume() apart from passing onPause() and onResume() through to the augScreen.
Awila_Tech 的回答也对我有帮助。我使用了 GLSurfaceView 并在 Activity 的 onPause 和 onResume 中巧妙地调用了它的 onPause 和 onResume,但是在调用实际的 onDrawFrame 时,五分之一的屏幕保持黑色。
总结一下:
Awila_Tech's answer helped me as well. I used a GLSurfaceView and neatly called its onPause and onResume in the Activities's onPause and onResume, but 1 out of 5 times my screen stayed black while the actual onDrawFrame was being called.
To summarize: