如何在Android上正确使用setZOrderMediaOverlay?

alo*_*oko 8 android z-order surfaceview glsurfaceview

像许多其他人一样,我试图在相机预览(使用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>
Run Code Online (Sandbox Code Playgroud)

<merge>

<code>

所有这些都包含在一个Preview块中,但出于某种原因,我无法将其包含在上面的SurfaceView列表中.setZOrderMediaOverlay()是扩展GLSurfaceView和实现相机预览逻辑的类.

这在活动启动时工作正常.在我启动另一个活动(例如,按下其中一个按钮)并完成该活动后,主活动将恢复,但3D对象不再可见.

我发现这个讨论的地方setZOrderMediaOverlay()有助于解决这个z排序问题.此外,setZOrderMediaOverlay()Android文档说"在将表面视图的包含窗口附加到窗口管理器之前"应该调用此函数.我不知道如何解释该语句,因此我将调试语句放在代码中以查看事件序列.这是onResume()代码的样子:


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

所以我假设setZOrderMediaOverlay()需要true在构造函数中或在构造函数中调用.不过,我试过的各种组合falseGLSurfaceViewSurfaceView,在setZOrderMediaOverlay()onResume()类,但没有它的问题有帮助.

在Android编程方面,我相对较新.我到目前为止,但此时我需要一些帮助.如果有人

<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>
Run Code Online (Sandbox Code Playgroud)

在这种情况下成功使用并使用它,请<merge>告诉我如何完成这项工作.

非常感谢提前!

小智 15

我已经在同一个问题上挣扎了一段时间,但相信下面的代码现在可行.(无论相机是打开还是关闭,它在暂停/锁定后继续工作).

首先,我没有在布局文件中定义任何视图等 - 它们是在代码中创建的.从main 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));
Run Code Online (Sandbox Code Playgroud)