SystemUI Flag詳解及使用情景

能夠造成SystemUI Flag被系統自動清除的交互分類

  1. 觸摸屏幕任何位置
  2. 頂部下拉狀態欄
  3. 底部上拉導航欄
  4. Window的變化(如:跳轉到其他界面、彈出鍵盤等)

SystemUI Flag 相關特性詳解

  1. View.SYSTEM_UI_FLAG_HIDE_NAVIGATION:(>=api16)
    作用是隱藏系統NavigationBar。
    但是用戶的任何交互,都會導致此Flag被系統清除,進而導航欄自動重新顯示,同時View.SYSTEM_UI_FLAG_FULLSCREEN也會被自動清除,因此StatusBar也會同時顯示出來。

  2. View.SYSTEM_UI_FLAG_FULLSCREEN:(>=api16)
    作用是隱藏StatusBar。
    WindowManager.LayoutParams.FLAG_FULLSCREEN有相同視覺效果。不同在於,此Flag一般用在暫時需要全屏的情形(如:閱讀應用,全屏視頻等),以便讓用戶的注意力暫時集中在內容上,而如果只是簡單的需要一直停留在全屏狀態(如:遊戲應用),使用WindowManager.LayoutParams.FLAG_FULLSCREEN則是更好的選擇。
    此Flag會因爲各種的交互(如:跳轉到其他應用,下拉StatusBar,彈出鍵盤)的發送而被系統清除。

  3. View.SYSTEM_UI_FLAG_IMMERSIVE:(>=api19)
    作用:避免某些用戶交互造成系統自動清除全屏狀態。

    • View.SYSTEM_UI_FLAG_IMMERSIVEView.SYSTEM_UI_FLAG_IMMERSIVE_STICKY的使用主要是爲了當設置全屏模式時,避免某些用戶交互造成系統自動清除全屏狀態。
    • 當使用View.SYSTEM_UI_FLAG_HIDE_NAVIGATION隱藏導航欄時,配合此特性,只有第三、四種操作會導致導航欄的隱藏狀態被系統自動清除;否則,任何交互都會導致導航欄的隱藏狀態被系統自動清除。
    • 此標識只有配合View.SYSTEM_UI_FLAG_HIDE_NAVIGATION纔有作用。
  4. View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY:(>=api19)
    作用:避免某些用戶交互造成系統自動清除全屏狀態。同時Activity的部分內容也因此被StatusBar覆蓋遮擋。

    • View.SYSTEM_UI_FLAG_HIDE_NAVIGATION隱藏導航欄,配合使用此Flag,只有用戶的第四種操作會導致狀態欄或(和)導航欄的隱藏狀態被系統自動清除。否則任何交互都會導致相應狀態的清除。
    • 此Flag只有配合SYSTEM_UI_FLAG_FULLSCREENSYSTEM_UI_FLAG_HIDE_NAVIGATION使用時纔會起作用。
  5. View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION:(>=api16)
    作用:在不隱藏導航欄的情況下,將Activity的顯示範圍擴展到導航欄底部。同時Activity的部分內容也因此被NavigationBar覆蓋遮擋。

    • 當使用此Flag時,設置fitSystemWindow=true的view,會被系統自動添加大小爲NavigationBar高度相同的paddingBottom。
    • 當window設置WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION時,此Flag會被系統會自動添加。
  6. View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN:(>=api16)
    作用:在不隱藏StatusBar的情況下,將view所在window的顯示範圍擴展到StatusBar下面。同時Activity的部分內容也因此被StatusBar覆蓋遮擋。

    1. 當使用此Flag時,設置fitSystemWindow=true的view,會被系統自動添加大小爲statusBar和ActionBar高度之和相同的paddingTop。
    2. 當window設置WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS時,此Flag會被系統會自動添加。
  7. View.SYSTEM_UI_FLAG_LAYOUT_STABLE:
    作用: 穩定佈局。當StatusBar和NavigationBar動態顯示和隱藏時,系統爲fitSystemWindow=true的view設置的padding大小都不會變化,所以view的內容的位置也不會發生移動。

    • 當使用SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN或SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION),同時view設置fitSystemWindow=true時,系統會爲此View自動設置padding。此padding的大小由View.fitSystemWindows(Rect)的Rect提供。一般情況下,當StatusBar和NavigationBar顯示時,paddingTop的大小爲StatusBar的高度。如果設置了getWindow().requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY),paddingTop的大小則爲StatusBar和ActionBar的高度之和。paddingBottom的大小則爲NavigationBar的高度。當StatusBar和NavigationBar被隱藏時,View的padingBottom和paddingTop的大小就變成了0, 因此StatusBar和NavigationBar的顯示和隱藏造成的padding變化,進而View內容的位置變化,從而造成位置閃動的視覺效果,影響體驗。
      使用SYSTEM_UI_FLAG_LAYOUT_STABLE的作用便是當StatusBar和NavigationBar的顯示和隱藏,系統爲View設置的padding都不會變化,因此View內容的位置不會變化,此即爲穩定佈局。
      -. (SYSTEM_UI_FLAG_FULLSCREEN |SYSTEM_UI_FLAG_LAYOUT_STABLE)時,
      會同時隱藏Actionbar和StatusBar,但StatusBar所佔空間不會隱藏,只會變成空白。同時View所在window的顯示範圍也不會伸展到StatusBar所佔空間。若是加上SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,View所在window的顯示範圍則會伸展到StatusBar所在的空間。
      同樣對NavigationBar如此操作,也會是一樣的效果。
    1. 當你設置了SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN時,配合此特性,若此時設置或取消SYSTEM_UI_FLAG_FULLSCREEN,不會因爲StatusBar的顯示或隱藏不會造成內容view的不穩定。
    2. 當你設置了SYSTEM_UI_FLAG_LAYOUT_FULLSCREENSYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,配合此特性,若此時設置或取消SYSTEM_UI_FLAG_FULLSCREENSYSTEM_UI_FLAG_HIDE_NAVIGATION,不會因爲StatusBar和導航欄的顯示或隱藏不會造成內容view的不穩定。
    3. 此特性不應該只配合SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION使用
    4. 使用WindowManager.LayoutParams.FLAG_FULLSCREEN(而不是使用SYSTEM_UI_FLAG_FULLSCREEN)來隱藏StatusBar是一個一直持續隱藏的狀態。這時你仍然可以使用SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_LAYOUT_STABLE隱藏Actionbar,並且不會因爲ActionBar的顯示或隱藏而不穩定。

fitSystemWindow

只有設置了View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATIONView.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,View的 fitSystemWindow=true纔會有效果。

WindowManager 相關特性詳解

  1. WindowMananger.FLAG_TRANSLUCENT_STATUS: (>=api16)

    1. 半透明StatusBar,並且不會因用戶交互而被清除。
    2. 設置了此flag,系統會自動設置View.SYSTEM_UI_FLAG_LAYOUT_STABLEView.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
  2. WindowMananger.FLAG_FULLSCREEN

    1. 用於隱藏StatusBar
    2. 使用此flag,系統會自動忽略輸入法的SOFT_INPUT_ADJUST_RESIZE的特性。
  3. WindowMananger.FLAG_TRANSLUCENT_NAVIGATION
    1.半透明NavigationBar,並且不會因用戶交互而被清除。
    2.設置了此flag,系統會自動設置View.SYSTEM_UI_FLAG_LAYOUT_STABLEView.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
    最低版本支持:Android4.4 (api 19)

  4. WindowMananger.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
    1.用於未StatusBar和NavigationBar設置背景顏色。
    2.原理:將StatusBar和NavigationBar設置爲透明背景,並且將StatusBar和NavigationBar所在空間設置爲Window.getStatusBarColor()Window.getNavigationBarColor()方法獲得的顏色。
    最低版本支持:Android5.0 (api 21)

SystemUI Flag引起的軟鍵盤變化

在使用SOFT_INPUT_ADJUST_RESIZE
同時View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN或View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION時,當鍵盤彈出時,只會fitSystemWindow=true的view所佔區域會被resize,其他view將會被軟鍵盤覆蓋。

常用情形

  1. 隱藏狀態欄
    代碼實例1
private fun hideStatusBar(){
    layout.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN
}

注意:用戶的第二、四類交互操作都會使系統自動清除狀態欄隱藏狀態(系統會自動取消View.SYSTEM_UI_FLAG_FULLSCREEN的設置)

代碼實例2

private fun hideStatusBar(){
    var tag = (View.SYSTEM_UI_FLAG_FULLSCREEN
            or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
    layout.systemUiVisibility = tag
}

注意:用戶的第四類交互操作會使系統自動清除狀態欄隱藏狀態(系統會自動取消View.SYSTEM_UI_FLAG_FULLSCREEN的設置,但是不會取消View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);用戶的第二類操作會使狀態欄暫時顯示,延遲幾秒後自動消失。

代碼實例3

private fun hideStatusBar(on: Boolean) {
    val winParams = window.attributes
    val bits = WindowManager.LayoutParams.FLAG_FULLSCREEN
    if (on) {//隱藏狀態欄
        winParams.flags = winParams.flags or bits
    } else {//顯示狀態欄
        winParams.flags = winParams.flags and bits.inv()
    }
    window.attributes = winParams
}

注意:1.用戶任何交互操作都不會使系統自動清除狀態欄隱藏狀態;用戶的第二類操作會是狀態欄暫時顯示,延遲幾秒後自動消失。
2.使用此flag,系統會自動忽略輸入法的SOFT_INPUT_ADJUST_RESIZE的特性。

  1. 透明狀態欄
    代碼實例1:半透明狀態欄
private fun translateStatusBar(on: Boolean) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        var p = window.attributes
        p.flags = p.flags or WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
        window.attributes = p
    }
}

注意:爲避免狀態欄遮擋View上的部分信息,需要爲View設置fitSystemWindow=true,或手動設置padding

代碼實例2:透明狀態欄

private fun translateStatusBar() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
        window.statusBarColor = Color.TRANSPARENT
        var tag = (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
        layout.systemUiVisibility = tag
    }
}

注意:
- Android的狀態欄的字體顏色默認爲白色,只有Android6.0以後才提供官方的API選擇黑色字體(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR)。所以當6.0以下使用透明狀態欄時,若StatusBar下面的View的也爲白色背景時,則會造成看不到StatusBar的相關信息。
- 爲避免狀態欄遮擋View上的部分信息,需要爲View設置fitSystemWindow=true,或手動設置padding

  1. 隱藏導航欄
    代碼實例1
private fun hideNavigationBar(){
    layout.systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
}

注意:用戶的任何操作都會使系統自動清除此狀態。SYSTEM_UI_FLAG_HIDE_NAVIGATION被系統自動清除時會連帶清除SYSTEM_UI_FLAG_FULLSCREEN

代碼實例2

private fun hideNavigationBar(){
    var tag = (View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
            or View.SYSTEM_UI_FLAG_IMMERSIVE)
    layout.systemUiVisibility = tag
}

注意:用戶的第三、四類交互操作會使系統自動清除此狀態;用戶的第二類操作會是狀態欄暫時顯示,延遲幾秒後自動消失

代碼實例3

private fun hideNavigationBar(){
    var tag = (View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
            or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
    layout.systemUiVisibility = tag
}

注意:用戶的第四類交互操作會使系統自動清除此狀態;用戶的第三類操作會是使導航欄暫時顯示,延遲幾秒後自動消失

  1. 全屏模式
    代碼實例1:一般用於視頻播放的情形
private fun fullScreen(){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        var tag = (View.SYSTEM_UI_FLAG_FULLSCREEN
                or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_LAYOUT_STABL)
        layout.systemUiVisibility = tag
    } 
}

注意: 用戶的任何交互都會導致全屏狀態被系統清除

代碼實例2:一般用於沉浸閱讀的情形

private fun fullScreen(){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        var tag = (View.SYSTEM_UI_FLAG_FULLSCREEN
                or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                or View.SYSTEM_UI_FLAG_IMMERSIVE)
        layout.systemUiVisibility = tag
    } 
}

代碼實例3::一般用於遊戲等嚴格沉浸的情形

private fun fullScreen(){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        var tag = (View.SYSTEM_UI_FLAG_FULLSCREEN
                or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
        layout.systemUiVisibility = tag
    } 
}
  1. 修改SystemBar的顏色
    代碼實例1
private fun setSystemBarColor(int color){
    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS|WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
    window.statusBarColor = color
    window.navigationBarColor = color
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章