System Bar:表示・非表示の制御(<Api30)

投稿日:  更新日:

アプリケーションの種類によってはSystem Barを非表示にしたい場合があります。

例えば、没入したいゲームはStatus Barを非表示にして、システムからの割り込みを無くすことが望ましいでしょう。

System Barはデフォルトでアプリに表示されますが、プログラムで非表示にすることも可能です。

System Barの表示・非表示の制御について紹介します。

スポンサーリンク

View#systemUiVisibilityを使った制御

System barの表示・非表示の制御はView#systemUiVisibilityにフラグをセットすることで行われます。

フラグの動作は表の通りです。

フラグ
SYSTEM_UI_FLAG_*
System Bar
非表示
System Bar
再表示
FULLSCREENStatus Barの非表示上端からスワイプで再表示
HIDE_NAVIGATIONNavigation Barの非表示タッチで再表示
FULLSCREEN
  or HIDE_NAVIGATION
System Barの非表示タッチで再表示
LAYOUT_STABLE
  or FULLSCREEN
Contentsサイズを変更しない
Status Barの非表示
上端からスワイプで再表示
LAYOUT_STABLE
  or HIDE_NAVIGATION 
Contentsサイズを変更しない
Navigation Barの非表示
タッチで再表示
LAYOUT_STABLE
  or FULLSCREEN
  or HIDE_NAVIGATION
Contentsサイズを変更しない
System Barの非表示
タッチで再表示
IMMERSIVE
  or FULLSCREEN
Status Barの非表示上端からスワイプで再表示
IMMERSIVE
  or HIDE_NAVIGATION
Navigation Barの非表示下端からスワイプで再表示
IMMERSIVE
  or FULLSCREEN
  or HIDE_NAVIGATION
System Barの非表示上下端からスワイプで再表示
IMMERSIVE_STICKY
  or FULLSCREEN
Status Barの非表示上端からスワイプで一定時間表示
※黒の半透明
IMMERSIVE_STICKY
  or HIDE_NAVIGATION
Navigation Barの非表示下端からスワイプで一定時間表示
※黒の半透明
IMMERSIVE_STICKY
  or FULLSCREEN
  or HIDE_NAVIGATION
System Barの非表示上下端からスワイプで一定時間表示
※黒の半透明
LAYOUT_HIDE_NAVIGATIONSystem Bar背面へコンテンツ表示
※色はフラグが影響を及ぼす動作を表します。

ただし、View#systemUiVisibilityはApi30で非推奨になりました。≧Api30はWindowInsetsController#show( )/hide( )メソッドを用います。

スポンサーリンク

System Barの表示・非表示

表示・非表示の実行例です。

非表示の様子は子Viewのレイアウト属性を参照してください。layout_marginとpaddingとgravityを使って実現されている事が分かります。

【参考】レイアウト属性をダンプするメソッド
    fun dumpViewStructure(view: View) {
        val _parent = view.parent
        if(_parent is ViewGroup) {
            Log.i(TAG, "Class = ${_parent.javaClass.simpleName}")
            _parent.forEachIndexed { index, view ->
                Log.i(TAG, "  Class = ${view.javaClass.simpleName}")
                val _XY = IntArray(2)
                view.getLocationInWindow(_XY)
                Log.i(TAG, "    Position = (${_XY[0]}, ${_XY[1]})")
                Log.i(TAG, "    Size     = ${view.width}x${view.height}")
                if(_parent is FrameLayout) {
                    val _params = view.layoutParams as FrameLayout.LayoutParams
                    // MATCH_PARENT -> -1, WRAP_CONTENT -> -2
                    Log.i(TAG, "    Layout Width, Height = %d,%d".format(
                            _params.width,
                            _params.height
                        ))
                    Log.i(TAG, "    Layout Margin LTRB   = %d,%d,%d,%d".format(
                            _params.leftMargin,
                            _params.topMargin,
                            _params.rightMargin,
                            _params.bottomMargin
                        ))
                    // BOTTOM -> 80, TOP -> 48
                    Log.i(TAG, "    Layout Gravity       = %d".format(
                            _params.gravity
                        ))
                }
                Log.i(TAG, "    Padding LTRB         = %d,%d,%d,%d".format(
                        view.paddingLeft,
                        view.paddingTop,
                        view.paddingRight,
                        view.paddingBottom
                    ))
                // VISIBLE   -> 0, INVISIBLE -> 4, GONE -> 8
                Log.i(TAG, "    Visibility           = %d".format(
                    view.visibility
                ))
            }
            dumpViewStructure(_parent)
        }
    }

FULLSCREEN(4)※( )内はフラグの値

Status Barを非表示にします。

非表示にされたStatus Barは上端からのスワイプで再表示できます。

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        ...
	    window.decorView.systemUiVisibility = SYSTEM_UI_FLAG_FULLSCREEN
	    ...
	}
【FULLSCREEN】

SYSTEM_UI_FLAG_FULLSCREEN
※LTRB : Left,Top,Right,Bottom
【子Viewのレイアウト属性】

Class = DecorView
  Class = LinearLayout(Contents)
    Position = (0, 0)
    Size     = 320x432
    Layout Width, Height = -1,-1
    Layout Margin LTRB   = 0,0,0,48
    Layout Gravity       = -1
    Padding LTRB         = 0,0,0,0
    Visibility           = 0(Visible)
  Class = View(Navigation)
    Position = (0, 432)
    Size     = 320x48
    Layout Width, Height = -1,48
    Layout Margin LTRB   = 0,0,0,0
    Layout Gravity       = 80(Bottom)
    Padding LTRB         = 0,0,0,0
    Visibility           = 0(Visible)
  Class = View(Status)
    Position = (0, 0)
    Size     = 320x0
    Layout Width, Height = -1,0
    Layout Margin LTRB   = 0,0,0,0
    Layout Gravity       = 48(Top)
    Padding LTRB         = 0,0,0,0
    Visibility         = 4(Invisible)

HIDE_NAVIGATION(2)

Navigation Barを非表示にします。

非表示にされたNavigation Barは画面のタッチで再表示できます。

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        ...
	    window.decorView.systemUiVisibility = SYSTEM_UI_FLAG_HIDE_NAVIGATION
	    ...
	}
【HIDE_NAVIGATION】

SYSTEM_UI_FLAG_HIDE_NAVIGATION
※LTRB : Left,Top,Right,Bottom
【子Viewのレイアウト属性】

Class = DecorView
  Class = LinearLayout(Contents)
    Position = (0, 0)
    Size     = 320x480
    Layout Width, Height = -1,-1
    Layout Margin LTRB   = 0,0,0,0
    Layout Gravity       = -1
    Padding LTRB         = 0,24,0,0
    Visibility           = 0(Visible)
  Class = View(Navigation)
    Position = (0, 480)
    Size     = 320x0
    Layout Width, Height = -1,0
    Layout Margin LTRB   = 0,0,0,0
    Layout Gravity       = 80(Bottom)
    Padding LTRB         = 0,0,0,0
    Visibility         = 4(Invisible)
  Class = View(Status)
    Position = (0, 0)
    Size     = 320x24
    Layout Width, Height = -1,24
    Layout Margin LTRB   = 0,0,0,0
    Layout Gravity       = 48(Top)
    Padding LTRB         = 0,0,0,0
    Visibility           = 0(Visible)

LAYOUT_STABLE(256)

System Barが非表示になっても、Contents Viewの位置とサイズは変更されません。

つまり、空いたSystem Barの領域へContents Viewが広がらないので、System Barの表示・非表示の前後でContents Viewの画像が乱れません(変化しません)。

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        ...
	    window.decorView.systemUiVisibility = SYSTEM_UI_FLAG_FULLSCREEN or
		    SYSTEM_UI_FLAG_HIDE_NAVIGATION or
			SYSTEM_UI_FLAG_LAYOUT_STABLE
	    ...
	}
【LAYOUT_STABLE】

SYSTEM_UI_FLAG_LAYOUT_STABLE
※LTRB : Left,Top,Right,Bottom
【子Viewのレイアウト属性】

Class = DecorView
  Class = LinearLayout(Contents)
    Position = (0, 0)
    Size     = 320x480
    Layout Width, Height = -1,-1
    Layout Margin LTRB   = 0,0,0,0
    Layout Gravity       = -1
    Padding LTRB         = 0,24,0,48
    Visibility           = 0(Visible)
  Class = View(Navigation)
    Position = (0, 432)
    Size     = 320x48
    Layout Width, Height = -1,48
    Layout Margin LTRB   = 0,0,0,0
    Layout Gravity       = 80(Bottom)
    Padding LTRB         = 0,0,0,0
    Visibility         = 4(Invisible)
  Class = View(Status)
    Position = (0, 0)
    Size     = 320x24
    Layout Width, Height = -1,24
    Layout Margin LTRB   = 0,0,0,0
    Layout Gravity       = 48(Top)
    Padding LTRB         = 0,0,0,0
    Visibility         = 4(Invisible)

非表示⇒表示の切り替え

System Barを「非表示⇒表示」に切り替えます。

View#systemUiVisibilityに指定したフラグをクリアすれば、System Barが表示された状態に戻ります。

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        ...
	    window.decorView.systemUiVisibility = 0
	    ...
	}
スポンサーリンク

System Barの再表示

非表示にしたSystem Barは画面の操作で再表示できます。その操作方法がフラグにより決まります。

再表示の実行例です。

IMMERSIVE(2048)

非表示にされたSystem Barは画面の上部または下部からのスワイプで再表示されます。

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        ...
	    window.decorView.systemUiVisibility = SYSTEM_UI_FLAG_FULLSCREEN or
		    SYSTEM_UI_FLAG_HIDE_NAVIGATION or
			SYSTEM_UI_FLAG_IMMERSIVE
	    ...
	}

IMMERSIVE_STICKY(4096)

非表示にされたSystem Barは画面の上部または下部からのスワイプで再表示(黒の半透明)されます。ただし、一定時間の経過後に再び非表示になります。

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        ...
	    window.decorView.systemUiVisibility = SYSTEM_UI_FLAG_FULLSCREEN or
		    SYSTEM_UI_FLAG_HIDE_NAVIGATION or
			SYSTEM_UI_FLAG_IMMERSIVE_STICKY
	    ...
	}
スポンサーリンク

System Barの背面へコンテンツ表示

通常、System Barとコンテンツは重なり合いません。この重なり合いを許して、System Barの背面へコンテンツの表示が可能です。

ただし、Sysytem Barを半透明にする必要があります。System Barの背面にあるコンテンツが見えなければ、意味が無いからです。

背面へコンテンツを表示する実行例です。

背面へ表示する様子は子Viewのレイアウト属性を参照してください。layout_marginとpaddingとgravityを使って実現されている事が分かります。

LAYOUT_HIDE_NAVIGATION(512)

System Barの背面にContents Viewが表示されます。

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        ...
	    window.decorView.systemUiVisibility = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
	    ...
		// System Barの背景の透明度を変更
		val _SystemBarColor = ContextCompat.getColor(this, R.color.barback)
        window.navigationBarColor = _SystemBarColor
        window.statusBarColor = _SystemBarColor
		...
	}
<?xml version="1.0" encoding="utf-8"?>
<resources>
    ...
    <color name="barback">#50ffffff</color>
	...
</resources>
【LAYOUT_HIDE_NAVIGATION】

SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
※LTRB : Left,Top,Right,Bottom
【子Viewのレイアウト属性】

Class = DecorView
  Class = LinearLayout(Contents)
    Position = (0, 0)
    Size     = 320x480
    Layout Width, Height = -1,-1
    Layout Margin LTRB   = 0,0,0,0
    Layout Gravity       = -1
    Padding LTRB         = 0,0,0,0
    Visibility           = 0(Visible)
  Class = View(Navigation)
    Position = (0, 432)
    Size     = 320x48
    Layout Width, Height = -1,48
    Layout Margin LTRB   = 0,0,0,0
    Layout Gravity       = 80(Bottom)
    Padding LTRB         = 0,0,0,0
    Visibility           = 0(Visible)
  Class = View(Status)
    Position = (0, 0)
    Size     = 320x24
    Layout Width, Height = -1,24
    Layout Margin LTRB   = 0,0,0,0
    Layout Gravity       = 48(Top)
    Padding LTRB         = 0,0,0,0
    Visibility           = 0(Visible)
スポンサーリンク

関連記事:

System Barはプログラマ側で記述をしなくても、デフォルトでアプリケーション画面に表示されます。 何処かで表示されるような構成になっているのです。 System Barが表示される仕組みを調べたので紹介します。 ...
アプリケーションの種類によってはSystem Barを非表示にしたい場合があります。 例えば、没入したいゲームはStatus Barを非表示にして、システムからの割り込みを無くすことが望ましいでしょう。 System Barはデフォルトでアプリに表示されますが、プログラムで非表示にすることも可能です。 System Barの表示・非表示の制御について紹介します。 ...
フルスクリーン(全画面モード)でコンテンツを提供することに適したアプリケーションがあります。 例えば、動画プレーヤー、ゲーム、電子書籍リーダ、画像エディター、スライドショーなどです。 アンドロイドはフルスクリーンを3つのモードに分類しています。 ...
エッジ―ツーエッジ(EdgeToEdge)について、まとめます。 エッジ―ツーエッジは言葉の通りに解釈すれば「端から端まで」ですから、見た目はフルスクリーンです。 しかし、新たな画面構成であり、フルスクリーンとは別物と定義されています。 最近は、様々なスクリーン形状を持つ端末が登場しています。 それらで、マルチウィンドウを実現するために、エッジツーエッジの対応が必須の条件になるようです。APIがエッジツーエッジを前提に作られているためです。 ですので、エッジ―ツーエッジは、今後のアプリ開発で重要な技術要素と言えます。 ※マルチウィンドウ:分割画面、フリーフォーム、PinP ※環境:Android Studio Jellyfish | 2023.3.1 Patch 1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.appcompat:appcompat 1.6.1 ...
スポンサーリンク