我们一直在与SurfaceViews相关的一些问题进行斗争一个多星期,并找不到合适的解决方案。我们在论坛中阅读了有关类似问题的其他问题(甚至是Mixare源代码),但找不到答案,所以我们希望你能以某种方式帮助我们。
方案: 我们有
问题:
无论我们尝试多么努力,两个SurfaceViews显然都不能相处得很好。如果我们尝试:
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和info视图之后锁定/解锁)。
问题是,我们正在寻找更优雅的解决方案。
在我们看来,问题是相机在Camera.open()
中花费的时间比预期的多,因此添加了相机视图,添加了GLSurfaceView,当相机实际打开时,它会打开GLSurfaceView。关于这一点,我们在GLSurfaceView上使用bringToFront()
,并将其放在信息视图的顶部,但在锁定/解锁后,相机仍在其上方打开,只留下一个带有相机预览的屏幕。 / p>
有什么想法吗?我们如何在它们之上显示SurfaceViews和信息视图?
答案 0 :(得分:5)
试试这个:
mLayout.addView(mRenderView);
mLayout.addView(mCustomSurfaceView);
// without this line, the camera preview cannot be displayed
// when running activity at first time.
mCustomSurfaceView.setZOrderMediaOverlay(true);
这对我有用:)
答案 1 :(得分:3)
我遇到了同样的问题。当你暗示自己:多个SurfaceView
s彼此不相处,因为它们的Z顺序是未定义的。
在我的三星Galaxy S2上,订购与您描述的相同(不知道它在其他手机上是怎样的)。
我解决这个问题的方法是检查第一次在Activity
中创建onCreate()
:
@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)
答案 2 :(得分:1)
我遇到了同样的问题:我想在GLSurfaceView下使用SurfaceView,第一个播放视频,第二个播放游戏。
无论我做了什么,这两个表面视图之间的z顺序似乎是随机的。
但是我找到了解决方案,感谢这篇文章:https://stackoverflow.com/a/6028907/1557915
诀窍是删除布局的使用,而是使用setContentView / addContentView。
答案 3 :(得分:1)
每个SurfaceView的表面都有Z深度。有三种可能的深度:默认(底部),"媒体覆盖" (在它之上)," top" (高于一切,包括基于视图的UI)。如果在相同深度处有两个重叠的表面,则会赢一个,但您无法可靠地定义哪一个。您可能会在一台设备上获得一致的行为,但却发现它在另一台设备上以其他方式工作。
尽可能使用硬件覆盖完成合成。许多目前流行的设备有4个覆盖平面。一旦超过这个,组合就完成了GPU,这将更加昂贵。如果你有一个状态栏,导航栏和View UI,那就是三个,所以你只能获得一个便宜的SurfaceView。
对于问题中的示例,最好将尽可能多的东西组合到使用GLES渲染的曲面上。这可以包括API 11+上的摄像头输出。请参阅"相机纹理"例如Grafika中的活动。 (Grafika还有一个带有三个重叠SurfaceView的演示应用程序;请参阅"多表面测试"活动。)
如果您想了解有关SurfaceView行为方式的更多信息,请参阅Android System-Level Graphics doc。