フルスクリーン(全画面モード)でコンテンツを提供することに適したアプリケーションがあります。
例えば、動画プレーヤー、ゲーム、電子書籍リーダ、画像エディター、スライドショーなどです。
アンドロイドはフルスクリーンを3つのモードに分類しています。
目次
フルスクリーンモード(全画面モード)
フルスクリーンは用途の違いにより、3つのモードに分類できます。
モード | 適したコンテンツ | 再表示する方法 (画面の操作) | アプリ例 |
---|---|---|---|
鑑賞モード | 画面を頻繁に操作しない | タップ | 動画プレーヤー スライドショー |
没入モード | 画面を頻繁に操作する | 上下端からスワイプ | ゲーム (キャラ移動を画面操作) 電子書籍リーダ (ページ送りで画面操作) |
アプリ優先型 没入モード | 画面を頻繁に操作する | 上下端からスワイプ ・黒の半透明 ・一定時間後に非表示 ・アプリでも処理 | 画像エディター (領域選択で画面操作) |
フルスクリーンはSystem Barが非表示なので、携帯端末はそのアプリケーションのみを実行しているように振舞います。
しかし、通知のチェックやちょっとした検索など、ユーザの要求に応じた処理も行わなければなりません。
その時はフルスクリーンを終了し、システムにアクセスが可能な状態へ移行するため、System Barを再表示させます。
通常、System Barを再表示させる方法は画面の操作で行われ、モードに適したものが割り当てられます。
鑑賞モード(Lead back mode)
画面を頻繁に操作しないコンテンツに適したモードです。
System Barを再表示する画面の操作は、簡素な「画面のタッチ」になります。
これは、System Barを再表示する画面の操作のみを考慮すればよいためです。
※System Barを非表示にする制御は次の記事を参照してください。
System Bar:表示・非表示の制御(<Api30)
System Bar:表示・非表示の制御(≧Api30)
override fun onResume() { super.onResume() hideSysBarInLeadBack() } // -------------------------------------------------------------- private fun hideSysBarInLeadBack() { // System Barを非表示 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { window.decorView.windowInsetsController?.apply { hide(WindowInsets.Type.systemBars()) systemBarsBehavior = BEHAVIOR_SHOW_BARS_BY_TOUCH } } else { window.decorView.systemUiVisibility = ( SYSTEM_UI_FLAG_FULLSCREEN or SYSTEM_UI_FLAG_HIDE_NAVIGATION ) } } private fun showSysBar() { // System Barを表示 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { window.decorView.windowInsetsController?.apply { show(WindowInsets.Type.systemBars()) } } else { window.decorView.systemUiVisibility = 0 } }
没入モード(Immersive mode)
画面を頻繁に操作するコンテンツに適したモードです。
System Barを再表示する画面の操作は、複雑さを持たせた「画面の上下端からのスワイプ」になります。
これは、コンテンツの操作とSystem barを再表示する操作を区別(同じにならないように)する必要があるためです。
System Barを非表示にする制御は次の記事を参照してください。
System Bar:表示・非表示の制御(<Api30)
System Bar:表示・非表示の制御(≧Api30)
override fun onResume() { super.onResume() hideSysBarInImmersive() } // -------------------------------------------------------------- private fun hideSysBarInImmersive() { // System Barを非表示 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { window.decorView.windowInsetsController?.apply { hide(WindowInsets.Type.systemBars()) systemBarsBehavior = BEHAVIOR_SHOW_BARS_BY_SWIPE } } else { window.decorView.systemUiVisibility = ( SYSTEM_UI_FLAG_IMMERSIVE or SYSTEM_UI_FLAG_FULLSCREEN or SYSTEM_UI_FLAG_HIDE_NAVIGATION ) } } private fun showSysBar() { // System Barを表示 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { window.decorView.windowInsetsController?.apply { show(WindowInsets.Type.systemBars()) } } else { window.decorView.systemUiVisibility = 0 } }
アプリ優先型没入モード(Sticky immersive mode)
画面を頻繁に操作するコンテンツに適したモードです。
System Barを再表示する画面の操作は、複雑さを持たせた「画面の上下端からのスワイプ」になります。
ただし、コンテンツの操作とSystem barを再表示する操作を区別しません。両者に対する操作として受け付けます。
コンテンツの操作が優先して行われ、フルスクリーンが継続されます。フルスクリーンの表示を妨げないように、System Bar(黒の半透明)は一時的な再表示になります。
System Barを非表示にする制御は次の記事を参照してください。
System Bar:表示・非表示の制御(<Api30)
System Bar:表示・非表示の制御(≧Api30)
override fun onResume() { super.onResume() hideSysBarInStickImmersive() } // -------------------------------------------------------------- private fun hideSysBarInStickImmersive() { // System Barを非表示 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { window.decorView.windowInsetsController?.apply { hide(WindowInsets.Type.systemBars()) systemBarsBehavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE } } else { window.decorView.systemUiVisibility = ( SYSTEM_UI_FLAG_IMMERSIVE_STICKY or View.SYSTEM_UI_FLAG_FULLSCREEN or SYSTEM_UI_FLAG_HIDE_NAVIGATION ) } } private fun showSysBar() { // System Barを表示 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { window.decorView.windowInsetsController?.apply { show(WindowInsets.Type.systemBars()) } } else { window.decorView.systemUiVisibility = 0 } }
バックグラウンドから復帰でフルスクリーン
フルスクリーンの状態からActivityがバックグラウンドへ遷移すると、System Barの非表示は解除されてしまいます。ダイアログが表示された場合などが、これに当てはまります。
よって、再びフォアグラウンドに復帰した時、フルスクリーンになりません。
これを回避し、フルスクリーンを維持したければ、フォアグラウンドへ復帰する時点でSystem Barの非表示を再指定します。
回避方法1:onResumeで非表示を指定
フォアグラウンドへ復帰する時は必ずonResume( )が呼ばれるので、ここで非表示の指定を実行します。
override fun onResume() { super.onResume() hideSysBarInXXX() // System Barを非表示 }
回避方法2:onWindowFocusChangedで非表示を指定
フォアグラウンドのViewが切り替わる時は必ずフォーカスの移動(変更)が伴います。このフォーカスの移動をトリガにして、非表示の指定を実行します。
override fun onWindowFocusChanged(hasFocus: Boolean) { super.onWindowFocusChanged(hasFocus) if(hasFocus) { hideSysBarInXXX() // System Barを非表示 } }
System Barの表示・非表示のイベント処理
System Barが表示・非表示になった時のイベント処理をしたければ、リスナーを登録します。
「≧Api30」と「<Api30」で使えるリスナーが異なっているので注意してください。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { window.decorView.setOnApplyWindowInsetsListener( object : OnApplyWindowInsetsListener { override fun onApplyWindowInsets(v: View, insets: WindowInsets) : WindowInsets { val _flag = (WindowInsets.Type.statusBars() or WindowInsets.Type.navigationBars()) if(insets.isVisible(_flag)) // systemBars()は使用不可 // System Barが表示の時 else // System Barが非表示の時 return v.onApplyWindowInsets(insets) // 下位へ実行を伝搬させる } }) } else { window.decorView.setOnSystemUiVisibilityChangeListener { visibility -> val _flag = (SYSTEM_UI_FLAG_FULLSCREEN or SYSTEM_UI_FLAG_HIDE_NAVIGATION) if(visibility and _flag == 0) // System Barが表示の時 else // System Barが非表示の時 } }
「≧Api30」のリスナー登録
OnApplyWindowInsetsListenerを使います。「≧Api30」で追加になったクラスです。
WindowInsets#isVisible( )メソッドを用いてSystem Barの表示・非表示がチェックできます。
注意1:onApplyWindowInsets( )を実行
OnApplyWindowInsetsListenerを登録すると、onApplyWindowInsets( )の実行が子Viewへ伝搬しなくなります。
これは、登録した側のonApplyWindowInsets( )の実行が優先され、Viewが持つonApplyWindowInsets( )が実行されなくなるためです。
なので、リスナー中でViewが持つonApplyWindowInsets( )実行して伝搬を施します。
注意2:systemBars( )は使用不可
WindowInsets#isVisible( )の引数へsystemBars( )を用いると、System Barの表示・非表示に関係なくfalseが返ります。
なので、statusBars( )またはnavigationBars( )を用いるようにします。
「<Api30」のリスナー登録
OnSystemUiVisibilityChangeListenerを用います。「≧Api30」で非推奨になったクラスです。
System Barの表示・非表示の状態をvisibilityが持っています。
関連記事: