Android 去除“Viewing full screen”彈窗
這篇文章可結合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中有如下函式:
- 1、首先看看這個isImmersiveMode引數,系統是如何判斷當前是否為沉浸式的呢?
【/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,那麼就是沉浸式模式。
- 2、再看一下mHandler中是如何處理H.SHOW訊息的
再看看handleShow函式:
噹噹噹,這個時候那個彈窗就顯示出來了。
解決方案
既然我們要解決彈窗顯示的問題,那麼根據以上顯示彈窗的分析,方案就來了。
①mHandler中接收到訊息後不做show confirmation的操作;
②彈窗顯示後就呼叫其隱藏的操作;
③不傳送顯示彈框的訊息SHOW到mHandler中。
接下來分析一下這三種方案:
- ①mHandler中接收到訊息後不做show confirmation的操作
因為這個檔案是framework層的,所以就是要修改系統原始碼。而且一旦接收到訊息後不做show confirmation的操作,那麼系統中的所有應用沉浸式全屏的時候都不會彈出提示框,而非當前的沉浸式全屏引用。這樣的需求一般不是我們所需要的,不過當然也是一種方案,這種方案對於看不到系統原始碼的開發者來說並不友好。修改方案如下:
- ②彈窗顯示後就呼叫其隱藏的操作
其實從剛剛的原始碼分析可以看到,因此彈框,也就是handleHide裡做的事。而這個handleHide被執行到,就需要給mHandler傳送HIDE訊息。But, 傳送HIDE訊息的就兩處:
第一處:這個要螢幕沉浸式顯示的模式變更後才會執行(即退出沉浸式模式)。
第二處:很明顯,這是和VR相關的,我們一般用不到。
那麼,我們可以試試不通過傳送訊息,而是直接執行handleHide裡的操作呀!!!
好的,這個函式是私有的。如果APP想呼叫,可以通過反射。=-=,這個類好像是不對外的吧,反正反射也沒有啥用。。。親測沒成功。。。。
- ③不傳送顯示彈框的訊息SHOW到mHandler中
終極方法終於來了!!!
在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