1. 程式人生 > >Android9.0 完全隱藏導航欄、狀態列

Android9.0 完全隱藏導航欄、狀態列

需求:自定義介面全屏顯示,隱藏導航欄,狀態列

按照google的官方辦法,設定如下幾個Flag就可以隱藏導航欄:

View decorView = getWindow().getDecorView();
// Hide both the navigation bar and the status bar.
// SYSTEM_UI_FLAG_FULLSCREEN is only available on Android 4.1 and higher, but as
// a general rule, you should design your app to hide the status bar whenever you
// hide the navigation bar.
int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
              | View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);

google對這個方案做了說明:

  • With this approach, touching anywhere on the screen causes the navigation bar (and status bar) to reappear and remain visible. The user interaction causes the flags to be be cleared.(觸控式螢幕幕任何位置,導航欄都會重新出現並保持可見。因為使用者互動導致設定的flag被清除了)
  • Once the flags have been cleared, your app needs to reset them if you want to hide the bars again. See 
    Responding to UI Visibility Changes
     for a discussion of how to listen for UI visibility changes so that your app can respond accordingly.(如果想要導航欄再次隱藏,就要重新設定flag)
  • Where you set the UI flags makes a difference. If you hide the system bars in your activity's  method and the user presses Home, the system bars will reappear. When the user reopens the activity,  won't get called, so the system bars will remain visible. If you want system UI changes to persist as the user navigates in and out of your activity, set UI flags in  or .(不同地方設定UI Flag效果會有影響。在onResume或者onWindowFouncChanged()函式裡設定flag永久生效)
  • The method  only has an effect if the view you call it from is visible.(只有在View是可見狀態下,呼叫setSystemUiVisiblity才會生效)
  • Navigating away from the view causes flags set with  to be cleared. (離開當前view,會導致利用setSystemUiVisiblity()函式設定的flag被清除)

即該方案有一個問題:一觸控式螢幕幕,導航欄又重新出現

該問題的解決辦法是,將flag設定為如下就可以完全全屏,導航欄和狀態列都被隱藏(親測有效)

private WindowManager mWM = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View mMainView = inflater.inflate(R.layout.main, null);

WindowManager.LayoutParams lp = new WindowManager.LayoutParams(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);//顯示的優先順序可以調整,顯示的順序可以檢視WindowManagerPolicy中getWindowLayerFromTypeLw函式中的返回值
lp.x = 0;//顯示的起始位置x
lp.y = 0;//顯示的起始位置y
lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN;
lp.systemUiVisibility = 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;
mWM.addView(mMainView, lp);

官方對這幾個flag的解釋:

  • SYSTEM_UI_FLAG_HIDE_NAVIGATION

和FLAG_FULLSCREEN、FLAG_LAYOUT_IN_SCREEN一起使用會暫時隱藏導航欄。一旦使用者與介面發生互動,導航欄又會出現。

  • SYSTEM_UI_FLAG_LAYOUT_NAVIGATION

  • SYSTEM_UI_FLAG_IMMERSIVE

   只有和SYSTEM_UI_FLAG_HIDE_NAVIGATION一起使用才會有效。如果僅僅設定了SYSTEM_UI_FLAG_HIDE_NAVIGATION,沒有設定SYSTEM_UI_FLAG_IMMERSIVE,那麼只要使用者與介面進行互動,導航欄則又會出現。

  • SYSTEM_UI_FLAG_IMMERSIVE_STICKY

只有和SYSTEM_UI_FLAG_FULLSCREEN、SYSTEM_UI_FLAG_HIDE_NAVIGATION其中的一個或兩個一起使用時才會有效果。

  • SYSTEM_UI_FLAG_LAYOUT_STABLE

  • SYSTEM_UI_FLAG_FULLSCREEN

  • SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN