像许多其他对象一样,我正在尝试在相机预览(使用SurfaceView)上绘制3D对象(使用GLSurfaceView)以及顶部放置的一些按钮。我实际上有一个可以工作的原型(prototype),但是我无法使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>

所有这些都包装在<merge>块中,但是由于某些原因,我无法将其包括在上面的<code> list 中。 Preview是扩展SurfaceView并实现相机预览逻辑的类。

当 Activity 启动时,这可以正常工作。在启动另一个 Activity (例如,通过按一个按钮)并完成该 Activity 后,将继续执行主要 Activity ,但3D对象不再可见。

我发现this discussion提到setZOrderMediaOverlay()将有助于解决此z排序问题。此外,Android document for setZOrderMediaOverlay()表示应将此函数调用为“在将包含表面 View 的窗口附加到窗口管理器之前”。我不知道该如何解释该语句,因此我将debug语句放入代码中以查看事件的顺序。 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->可见
GLPreview:surfaceCreated
GLPreview:surfaceChanged,格式= 1,w = 800,h = 480

因此,我假设需要在setZOrderMediaOverlay()或构造函数中调用onResume()。但是,我在setZOrderMediaOverlay()true类中尝试了falseGLSurfaceViewSurfaceView的各种组合,但都无济于事。

对于Android编程,我还比较陌生。我到目前为止已经走了,但是在这一点上我需要一些帮助。如果有人在这种情况下成功使用了setZOrderMediaOverlay()并使其与onResume()一起使用,请告诉我该怎么做。

在此先多谢!

最佳答案

我在同一个问题上苦苦挣扎了一段时间,但相信下面的代码现在可以工作了。 (无论相机处于开启还是关闭状态,它在暂停/锁定后都可以继续工作)。

首先,我没有在布局文件中定义任何 View 等-它们是用代码创建的。从主要的onCreate()方法调用以下内容-注意augScreen上的setZOrderMediaOverlay()。

除了将onPause()和onResume()传递到augScreen之外,在onPause()或onResume()中我没有做任何特别的事情。

        // 1 - Camera Preview
        camScreen = new CameraPreview(this);
        setContentView(camScreen, new LayoutParams(
                LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));

    // 2 - 3D object display
        augScreen = new AR_SurfaceView(this, getViewRange());
        addContentView(augScreen, new LayoutParams(
                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
        augScreen.setZOrderMediaOverlay(true);

    // 3 - Permanent overlay
    RelativeLayout overlayScreen = new OverlayView(this);
    addContentView(overlayScreen, new LayoutParams(
            LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
    overlayScreen.setVisibility(View.VISIBLE);

    // 4 - UI buttons (toggleable)
        uiScreen = new UserInterfaceView(this);
        addContentView(uiScreen, new LayoutParams(
                LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));

10-08 16:24