检测状态栏可见性 / TYPE_SYSTEM_OVERLAY 不会自动调整大小

37

我正在使用众所周知的 TYPE_SYSTEM_OVERLAY 方法创建一个全屏叠加层,始终位于其他视图之上。

Moto Atrix2 API15 上,对于每个从 API 1017AVD,当状态栏被其他应用程序隐藏时,叠加视图会自动调整大小(在垂直方向上扩展)。我认为这个叠加层应该“始终位于其他视图之上”。当状态栏再次出现时,叠加层会自动缩小其大小(基本上是减去状态栏的高度)。

这是期望的行为,我倾向于认为这不是异常或有缺陷的行为,因为它在许多不同的模拟器上以及至少一个设备制造商(motorola)上都可以工作,可能还有更多,但我无法获得访问权限来测试 addtl devices

问题:Samsung GS2 (API15) 上(也在 Kindle Fire (API10?) 上测试),当状态栏被其他应用程序隐藏时(全屏应用程序的状态栏在后面),叠加层不会自动调整大小(填充状态栏曾经所在的空间)。在这些设备上,视图创建后第一次之后,我没有再收到关于视图大小更改的任何事件。

以下是相关代码:

params = new WindowManager.LayoutParams( 
    1, WindowManager.LayoutParams.MATCH_PARENT, 
    WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, 
    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
    |WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, 
    PixelFormat.TRANSPARENT);
wm.addView(sizeLayout, params);

sizeLayout有onSizeChanged覆盖。

我已经尝试过几乎每种windowmanager layoutparam,包括SYSTEM_ALERT、FLAG_LAYOUT_IN_SCREEN等等。我不会休息,直到我弄清楚它!

编辑11/30/12:我从@deviant那里找到了这个:https://dev59.com/EWsy5IYBdhLWcg3w9Szk#9195733,基本上就是我正在做的事情,但某些设备仍然无法自动调整system_overlay的大小。也许我应该提出一个错误报告。

更多信息:如果我在视图树的顶部有一个全屏应用程序时,强制重绘(甚至只是加载叠加层应用程序),我的叠加层仍然不会绘制在状态栏通常占据的空间上(即使状态栏在绘制时不可见),因此似乎叠加层没有"叠加"在最前面的全屏窗口之上(我创建并测试了许多全屏应用程序,使用各种方法使它们全屏)。在这些设备上,使叠加层绘制在状态栏上(即使状态栏不可见)的唯一方法是使用flag FLAG_LAYOUT_IN_SCREEN,但这样布局的大小永远不会改变,总是全屏,因此回到最初的问题:为什么这在某些设备上有效但在其他设备上无效。

编辑12/12/12:所以我在这方面没有进一步的运气,我确实尝试过在视图上使用 getLocalVisibleRect,但不幸的是,由于我的应用程序不拥有SystemUI视图,它无法检测叠加层下面的内容。我想,如果有一个定制的ROM,我可以做到这一点,但我需要一个没有root权限的解决方案。

我看到市场上的其他应用程序也遇到了在我上面列出的不起作用的手机上检测状态栏的同样的问题。例如:Cool Tool、Omega Statusbar和Status Bar+。赏金已经提高。

编辑12/19/12 添加图片。请注意,在工作正常的设备上,灰色区域也“覆盖”黑色区域(任何当前全屏的应用程序),黑色区域实际上覆盖整个屏幕,我只是将灰色区域显示为我的叠加层,即使它也是全屏的(减去或加上状态栏的高度,具体取决于工作/不工作的设备以及它是否在视图中)。

enter image description here enter image description here


请问您能否添加所需行为的屏幕截图以及您所得到的内容? - Anis BEN NSIR
你尝试过切换到全屏模式吗?在添加视图之前,请尝试以下代码: // 切换到全屏模式 WindowManager.LayoutParams attrs = mActivity.getWindow().getAttributes(); attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN; mActivity.getWindow().setAttributes(attrs); - Anis BEN NSIR
@Anis,是的,我已经尝试了full_screen标志,并且得到了相同的行为。然而,你的问题表明你可能没有完全理解这个问题,我建议你再读一遍。不过还是谢谢你的想法! :) - logray
2个回答

3
希望我能理解你想要的,但在我的应用程序(TEAM BatteryBar)中,我遇到了类似的问题。(无根最小权限)在API11以下的任何设备上都无法检测到全屏(在某些设备上(主要是三星),API11以上会间歇性出现)。因此,我通过向WindowManager添加第二个布局,并使用不同的布局参数来创建自定义监听器,然后重写onLayout以通过检查窗口大小来检查状态栏是否仍然存在。从那里,您可以对主视图进行任何需要的操作。我本来打算整理它,但它确实有效,所以我没有:P代码已经一年多了,是我开始为Android编写代码时的产物,所以这是一个值得思考的问题。希望它有所帮助。这里是我在github上的代码仓库,其中包含我如何使用它的应用程序的复制粘贴。这里是一个小片段。
wm.addView(sizeLayout, params);// add your view

// then add the next one
Screendetect mDetector;
mDetector = new Screendetect(this);
mDetector.setOnFullScreenListener(new OnFullScreenListener() {
            @Override
            public void fsChanged(boolean FS_Bool) {
                // TODO rethink this to be better.... bit hacky...
                if (FS_Bool) {
                    Log.d("battbardetect", "Statusbar hidden");
                    FS_vissible(); // do what ever you need to
                } else if (!FS_Bool) {
                    Log.d("battbardetect", "Statusbar Vissible"); 
                    FS_hidden(); // do what ever you need to
                }
            }
        });
wm.addView(mDetector, params);

1
好的,谢谢你的尝试。我尝试了你的代码,基本上是逐字逐句地复制,但是遇到了同样的问题,onLayout只在视图第一次添加(或配置更改)时调用一次,直到服务(或视图)被销毁/删除并再次创建/添加才会再次调用。即使我反复添加和删除视图,垂直大小也永远不会改变,除非我使用屏幕标志添加布局。所以基本上是相同的问题,至少在三星GS2 API15上测试过。顺便说一下,onSystemUiVisibilityChange也不起作用。我从那里得不到任何事件:GS2设备是带有物理导航键的ICS。 - logray
1
哦,顺便说一下,我在三星GS2上尝试了你的电池栏应用程序,你的应用程序有同样的问题,不能检测全屏应用程序(如果你在Kindle Fire上发布,猜测你的应用会有同样的问题)。 - logray
1
有趣,是某些/选择的全屏应用程序还是所有应用程序都有这个问题?(我注意到我忘记在免费版本中添加遗留检测选项,我今晚会更新)编辑三星固件可能存在漏洞?因为我的Sony API15可以同时使用。 - pvyParts
1
是的,任何全屏应用程序(甚至编写了几个自己来尝试不同的设置全屏方法,无论如何,也不管哪个示例YouTube /等)。 是的,我在考虑三星FW可能存在的错误,但它也会发生在Kindle Fire上,所以这让我开始怀疑... - logray
1
好的,我有一个朋友有一台S2,我会叫他过来玩一下。Kindle Fire 运行经过修改的API10(GB)或API15(ICS)(我想是这样),因此这个bug可能来自AOSP树。 - pvyParts
显示剩余2条评论

1

我认为这可能与隐藏对话框窗口的标题栏时出现的问题相同,系统将可见性设置为隐藏而不是消失。这会导致对话框窗口居中不正确。

针对此问题,以下是我解决它的方法。这可能适用于您的情况,但您可能需要根据状态栏标识符的名称进行调整。

Window window = dialog.getWindow();
View view = window.getDecorView();
int topPanelId = getResources().getIdentifier("topPanel", "id", "android");
LinearLayout topPanel = (LinearLayout) view.findViewById(topPanelId);
topPanel.setVisibility(View.GONE);

我相当确定这将需要root权限(也许还需要一个自定义的SystemUI.apk),而且我需要一个不需要这两者的解决方案。其次,我对隐藏状态栏并不感兴趣,只是想检测它是否可见。我会尝试一些方法,但我并不抱太大希望。 - logray
我没有成功设置一个我的应用程序不拥有的视图的可见性...谢谢你的尝试。 - logray

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接