フルスクリーン(全画面モード)でコンテンツを提供することに適したアプリケーションがあります。
例えば、動画プレーヤー、ゲーム、電子書籍リーダ、画像エディター、スライドショーなどです。
アンドロイドはフルスクリーンを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が持っています。
関連記事:
