与SurfaceView,Camera和OpenGL作战

| 我们已经在与SurfaceViews相关的一些问题上进行了超过一个星期的斗争,但没有找到合适的解决方案。我们在论坛上阅读了有关类似问题的其他问题(甚至包括Mixare源代码),但找不到答案,因此希望您能以某种方式帮助我们。 场景: 我们有 相机的SurfaceView OpenGL层的SurfaceView,位于相机顶部。 另一个视图,其中显示了一些我们可以在屏幕上看到的信息。这是两个SurfaceView的基础。 问题: 无论我们多么努力,两个SurfaceView显然都无法很好地相处。如果我们尝试:
setContentView(mCameraPreview); 
addContentView(mGLSurfaceView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 
addContentView(mInfoView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
(这似乎合乎逻辑),一切都按预期进行,直到我们锁定/解锁手机为止。在那之后,GLSurfaceView只是消失了(不是InfoView,那个仍然显示)。 相反,如果我们尝试:
setContentView(mGLSurfaceView); 
addContentView(mCameraPreview, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 
addContentView(mInfoView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
然后的问题是,GLSurfaceView仅在锁定/解锁之后出现,并且在此之前屏幕显示摄像机和InfoView。 我们发现,如果在显示视图的活动中执行onStart()之后使主线程休眠4.6秒(或更长时间),则行为与预期的一样(即使在锁定/解锁之后,也会显示相机,glsurface和信息视图) )。 问题是,我们正在寻找更...优雅的解决方案。 在我们看来,问题在于相机花费的时间比ѭ2中的预期时间还要长,因此添加了相机视图,添加了GLSurfaceView,并且当相机实际打开时,它在GLSurfaceView的顶部打开。关于这一点,我们在GLSurfaceView上使用了
bringToFront()
,并将其置于信息视图的顶部,但是在锁定/解锁相机之后,相机仍在其顶部打开,只剩下一个带有相机预览的屏幕。 有任何想法吗?我们如何在它们上面显示SurfaceViews和信息视图?     
已邀请:
尝试这个:
mLayout.addView(mRenderView);
mLayout.addView(mCustomSurfaceView);

// without this line, the camera preview cannot be displayed 
// when running activity at first time.
mCustomSurfaceView.setZOrderMediaOverlay(true);
这对我有用:)     
我有同样的问题。正如您对自己的暗示:多个
SurfaceView
彼此不相处,因为它们的Z顺序未定义。 在我的Samsung Galaxy S2上,订购顺序与您描述的相同(不知道其他手机的订购情况)。 我解决这个问题的方法是检查
onCreate()
中第一次创建
Activity
@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);

    //...

    if ( savedInstanceState == null )
    {
        initCamView();
        initOpenGL();
    }
    else
    {
        initOpenGL();
        initCamView();
    }

    //...
}
与:
private void initOpenGL()
{
    mGLSurfaceView = new GLSurfaceView(this);
    mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
    mGLSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);

    mOGLRenderer = new OGLRenderer(this);
    mGLSurfaceView.setRenderer(mOGLRenderer);
    mRL.addView(mGLSurfaceView); // mRL is the Relative Layout
}
和:
private void initCamView()
{
    mCamView = new CustomCameraView( this.getApplicationContext(),
                                     this.getWindowManager() );
    mRL.addView(mCamView); // mRL is the Relative Layout
}
这不是最优雅的解决方案,但是比让线程休眠4.6秒更好。 也可以将屏幕锁定在一个方向,但是您需要进行很多难看的修改,以使覆盖层以正确的方式旋转。 或者,如果您仅针对Android 3.0或更高版本(API级别8),则可以仅在OpenGL SurfaceTexture中显示相机。 http://developer.android.com/reference/android/hardware/Camera.html#setPreviewTexture(android.graphics.SurfaceTexture)     
我遇到了同样的问题:我想要在GLSurfaceView下使用SurfaceView,第一个播放视频,第二个运行游戏。 无论我做什么,这两个曲面视图之间的z顺序似乎都是随机的。 但是由于这篇文章,我找到了解决方案:https://stackoverflow.com/a/6028907/1557915 诀窍是取消使用布局,而是使用setContentView / addContentView。     
每个SurfaceView的表面都有一个Z深度。共有三种可能的深度:默认深度(底部),\“媒体覆盖\”(上方)和\“ top \”(位于一切之上,包括基于视图的UI)。如果在同一深度有两个重叠的曲面,则一个会获胜,但是您不能可靠地定义哪个曲面。您可能在一台设备上获得一致的行为,只是发现它在另一台设备上以另一种方式工作。 如有可能,使用硬件覆盖图进行合成。许多当前流行的设备具有4个覆盖平面。一旦超过此数量,GPU便会完成合成,这将变得更加昂贵。如果您有一个状态栏,导航栏和“视图”用户界面,则为三个,因此您只能以便宜的价格获得一个SurfaceView。 对于问题中的示例,最好将尽可能多的东西组合到使用GLES渲染的表面上。这可以包括API 11+上的相机输出。有关示例,请参见Grafika中的“相机中的纹理”活动。 (Grafika还有一个演示应用程序,具有三个重叠的SurfaceView;请参见“多表面测试”活动。) 如果您想进一步了解SurfaceView为何以这种方式运行,请参阅Android系统级图形文档。     

要回复问题请先登录注册