这篇文章可结合Android9.0 完全隐藏导航栏、状态栏
Android应用设置沉浸式全屏时,一般会使用到如下的Flag:
View.SYSTEM_UI_FLAG_IMMERSIVE或View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY以及View.SYSTEM_UI_FLAG_HIDE_NAVIGATION。
使用了以上的Flag组合后呢,系统会弹窗提示用户当前是全屏显示,弹框如下:
大标题是Viewing full screen,小字部分是Swipe down from the top to exit full screen.”的提示,即从上往下滑动可退出全屏。
这个提示是友好的,但是大多数情况下,这个提示框可能因为挡住了要显示的内容而不满足全屏要求。那么如何去除“Viewing full screen”弹窗呢?要去除这个弹框,就先要从这个弹框出现的位置开始分析。
在/framework/base/servics/core/java/com/server/policy/ImmersiveModeConfirmation.java中有如下函数:
【/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java】的函数updateSystemBarsLw:
vis就是来判断显示界面设置给systemUiVisibility 的flag的。看看isImmersiveMode:
也就是如果systemUiVisibility设置了SYSTEM_UI_FLAG_HIDE_NAVIGATION + SYSTEM_UI_FLAG_IMMERSIVE、SYSTEM_UI_FLAG_IMMERSIVE_STICKY中的一个或两个,且存在NavigationBar,那么就是沉浸式模式。
再看看handleShow函数:
当当当,这个时候那个弹窗就显示出来了。
既然我们要解决弹窗显示的问题,那么根据以上显示弹窗的分析,方案就来了。
①mHandler中接收到消息后不做show confirmation的操作;
②弹窗显示后就调用其隐藏的操作;
③不发送显示弹框的消息SHOW到mHandler中。
接下来分析一下这三种方案:
因为这个文件是framework层的,所以就是要修改系统源码。而且一旦接收到消息后不做show confirmation的操作,那么系统中的所有应用沉浸式全屏的时候都不会弹出提示框,而非当前的沉浸式全屏引用。这样的需求一般不是我们所需要的,不过当然也是一种方案,这种方案对于看不到系统源码的开发者来说并不友好。修改方案如下:
其实从刚刚的源码分析可以看到,因此弹框,也就是handleHide里做的事。而这个handleHide被执行到,就需要给mHandler发送HIDE消息。But, 发送HIDE消息的就两处:
第一处:这个要屏幕沉浸式显示的模式变更后才会执行(即退出沉浸式模式)。
第二处:很明显,这是和VR相关的,我们一般用不到。
那么,我们可以试试不通过发送消息,而是直接执行handleHide里的操作呀!!!
好的,这个函数是私有的。如果APP想调用,可以通过反射。=-=,这个类好像是不对外的吧,反正反射也没有啥用。。。亲测没成功。。。。
终极方法终于来了!!!
在ImmersiveModeConfirmation.java文件中,有且仅有一处发送了SHOW消息:
没错!!就是这个函数。那么为了不发送SHOW消息,所以就要if条件不满足。
通过分析,这个navBarEmpty条件最容易被APP修改,我们只要让这个值为true就好了。
那么来看看这个参数navBarEmpty的由来:
【/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java】
函数updateSystemBarsLw:
来看看isNavBarEmpty是个什么鬼:
没错,这要这个isNavBarEmpty返回true,就不会show 弹出了。
从这个函数可以看到,只要在应用界面显示的systemUiVisibility参数中加上这三个FLAG那么这个函数就会返回true。从而那个Viewing Full Screen的弹窗也不会出现了(亲测有用)。
修改如下:
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
lp.systemUiVisibility = View.STATUS_BAR_DISABLE_HOME | View.STATUS_BAR_DISABLE_BACK | View.STATUS_BAR_DISABLE_RECENT |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
这种方法,并不是对所有应用起作用。而仅仅是对自己的沉浸式全屏应用其作用,当应用退出时,这个弹窗还是对其他应用有效的。o(* ̄︶ ̄*)o