【问题标题】:SurfaceView hides other components on screenSurfaceView 隐藏屏幕上的其他组件
【发布时间】:2015-02-20 10:48:29
【问题描述】:

我正在创建一个 FrameLayout 类型的布局,我在其中添加了两个视图。两个视图分别是 GLSurfaceView 和 SurfaceView 的对象。根据有关 SurfaceView 的 Android 开发者文档,

“表面是 Z 顺序的,因此它位于持有其 SurfaceView 的窗口后面;SurfaceView 在其窗口上打一个孔以显示其表面。”

它对我很有效,SurfaceView 总是在我的 GLSurfaceView 后面(用于 opneGL 绘图)。但是在外部事件之后恢复,以下配置的行为很奇怪,

安卓版本:4.3 设备型号:Nexus 7 内核版本 3.4.0.g1f57c39 6月13日 内部版本号:JWR66N

对于此配置,在外部事件后恢复会将我的 GLSurfaceView 置于 SurfaceView 后面。换句话说,SurfaceView 位于 ZOrder 的顶部,而我的 OpenGL 绘图不再可见。在高于 Android 4.3 的版本上,不会出现此行为。

我可以通过调用 SurfaceView 的以下方法并将 true 作为参数复制到所有版本上。

void setZOrderOnTop

这是已知问题吗?有人可以帮我解决这个问题吗?

问候, 苏梅德

【问题讨论】:

  • 我打赌它依赖于设备......这个洞不是很可靠,并且容易在滚动、重新布局、恢复时出现伪影......
  • 有什么替代方案。我想在视频上放置一些控件,我可以使用哪些布局、视图。你能指点我吗.......
  • 嗯,你正在接近边缘!看看stackoverflow.com/questions/5647824/…,他们似乎在讨论surfaceviews的堆叠
  • 感谢您的信息。
  • 我注意到的一件事是这只发生在 Jellybean 上

标签: android surfaceview


【解决方案1】:

不要使用“setZOrderOnTop”作为真。这将使它超越所有其他布局。

如果您使用多个表面视图。对每个表面视图使用它

yourSurfaceView.setZOrderMediaOverlay(true);

然后将此 setZOrderOnTop 设置为您稍后启动的表面视图的 false 并希望它返回到其他表面视图

secondSurfaceview.setZOrderOnTop(false);

【讨论】:

    【解决方案2】:

    SurfaceViews 有两个部分,Surface 和 View。 Surface 是一个完全独立的层。视图在那里,所以 UI 布局代码可以使用。通常,视图只是透明的黑色,因此您可以看到它背后的任何东西。

    GLSurfaceView 只是带有一些代码来管理 EGL 上下文和线程的 SurfaceView。在它下面只是一个 SurfaceView。因此,如果您同时拥有 SurfaceView 和 GLSurfaceView,并且它们具有相同的尺寸和 Z 顺序,那么它们中的一个将“赢”而另一个将“输”,因为它们试图占据相同的位置同时空间。没有明确的值会“获胜”,因此预期会出现不一致的行为。

    避免冲突的一种方法是将一个设置保留为默认 Z,并在另一个上调用 setZOrderMediaOverlay()。 “媒体覆盖”仍然在 UI 后面,但在默认的 Surface 位置之上。如果您使用setZOrderOnTop(),Surface 也将位于 UI 上方。

    如果你想看到它后面的东西,上面的 Surface 需要用透明像素渲染(就像 View 需要透明才能看到 Surface)。

    避免此问题的最有效方法是不出现此问题:对所有内容使用一个 SurfaceView,将所有非 UI 元素内容呈现给它。如果您要在其中一个 Surface 上渲染视频或显示相机预览,这需要更多的工作(可能还有 SurfaceTexture)。

    您可以在Grafika 中找到一些示例。 “multi-surface exerciser”演示了三个在软件中呈现的重叠 SurfaceView,与 UI 元素重叠。其他活动展示了使用 Surfaces、GLES、相机和视频的方法。

    另请参阅 Android System-Level Graphics Architecture 文档,其中更详细地解释了所有这些。

    【讨论】:

    • 谢谢。我完全按照你的解释做了。这是我正在做的,我有两个视图 1. GLSurfaceView(绘制由 Cocos2dx 框架生成的图形),2. SurfaceView(渲染视频,媒体播放器)。我希望我的 cocos2dx 图形始终位于视频的顶部,因此我为 GLSurfaceView 调用 setZOrderMediaOverlay()。我假设因为我没有为 SurfaceView 设置任何 ZOrder 参数,所以它是默认的,并且总是在 GLSurfaceView 下方按 Z 顺序排列。分层与使用高于 Jelly bean 的操作系统的设备一起正常工作,对于 Jelly Bean 它不起作用。我错过了什么..或其他..
    • 我也浏览了系统级图形架构文档。我可以将它与 Jelly bean 关联的唯一方法是“数据结构当前始终由消费者创建和“拥有”。在 Android 4.3 中,只有生产者端被“绑定”,即生产者可能在远程进程中,但消费者必须生活在创建队列的过程中。这在 4.4 中有所发展,朝着更通用的实现方向发展。”,但我不认为这与 Z 顺序有任何关系。我正确吗
    • 如果您希望两者叠加,您需要确保顶部的一个(GLSurfaceView)使用正确的颜色格式并使用非透明 alpha 渲染像素。您可以使用adb shell dumpsys SurfaceFlinger 确认排序和颜色格式,查看硬件作曲家摘要部分(图形架构文档中的几个地方出现了一个缩减版本——表面按从后到前的顺序列出)。 Z 顺序调用必须发生在创建表面之前;我不记得 GLSurfaceView 是否允许您这样做。 Cocos2dx 可以用普通的 SurfaceView 吗?
    • 谢谢。我在分层时遇到了一些问题,现在我将 GLSurfaceView 设置为 Z 顺序设置为顶部,将 SurfaceView 设置为 setZOrderMediaOverlay(),它也适用于 Jelly bean。但是现在从外部事件恢复时,Z 顺序发生变化,GLSurfaceView 以某种方式比 SurfaceView 的 z 顺序更低,我又回到了整体。 Open GL 图形位于 Surfaceview 中的视频后面。这仅发生在果冻豆上。请参阅下一条评论,其中包含来自 SurfaceFlinger 的转储。
    • adb shell dumpsys here binbox.io/HXA7f#qwCvZNMk,如您所见,SurfaceFlinger 不考虑我的 GLSurfaceView(带有 Open GL 图纸)进行复合。这发生在果冻豆上……感谢您的意见……
    猜你喜欢
    • 2021-11-18
    • 1970-01-01
    • 2021-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 1970-01-01
    相关资源
    最近更新 更多