フルスクリーン画面対応のこれまでとこれから

Photo by Erik Mclean on Unsplash

Androidのバージョンアップとともに、フルスクリーン画面を実現する方法が変更されてきたので、まとめておきます。
さらに次のAndroid 12でも一部変更が入りそうな気配です。

これまでの対応方法

テーマ (Theme.Holo.NoActionBar.Fullscreen)もしくは Window.setFlags で実現していました。

window.setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN
)

ただ、この FLAG_FULLSCREEN はAPI Level 30からはDeprecatedになっています。

Android 4.1以降では、 setSystemUiVisibility を使って実現していました。

window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN

setSystemUiVisibility ではステータスバーの他にもナビゲーションバーも非表示にすることができるようになっています。

Immersiveモードも導入されています。

setSystemUiVisibility もAPI Level 30からはDeprecatedになっています。

上記のとおり、いずれの方法もDeprecatedになっているため、今後は別の方法で実現する必要があります。

Android 11の対応方法

Android 11 (API Level 30) から WindowInsetsController というのが追加されています。今後はこちらを使って対応していくことになります。

binding.root.windowInsetsController?.run {
hide(WindowInsets.Type.systemBars())
}

hide メソッドに隠したい WindowInsets.Type を設定することで実現できます。上の systemBars を使うとステータスバーとナビゲーションバーを両方を消すことが出来ます。
ナビゲーションバーは表示したままで、ステータスバーだけを消したい場合は、 hide(WindowInsets.Type.statusBars()) で実現できます。

あとから表示したい場合は show メソッドを同じように使用することで再び表示できます。

実行するタイミングですが、 onCreate 等の一回しか実行されない箇所でやってしまうとホーム画面から戻ったときにそのまま表示されたままになるので、 onResume 等でやるほうが良いでしょう。

systemBarsBehavior にてステータスバーやナビゲーションバーの再表示の挙動を指定することができます。

  • BEHAVIOR_SHOW_BARS_BY_TOUCH: 画面をタップなどのユーザーが何かしら操作したときに表示されます。(デフォルト)
  • BEHAVIOR_SHOW_BARS_BY_SWIPE: 画面の上か下をスワイプすると表示されます。
  • BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE: こちらも画面の上から下をスワイプすると表示されますが、表示後にしばらくすると自動でまた非表示になります。Sticky immersiveのような動きになります。

Android 12からの対応

これを書いてる時点ではAndroid 12はDeveloper Preview2ですが、すでに変更が入るようです。

systemBarsBehavior に設定する値に変更が入ります。まだDeveloper Preiewなので更に変更があるかもですが、注意が必要です。

BEHAVIOR_SHOW_BARS_BY_SWIPE はDeprecatedになり、 BEHAVIOR_DEFAULT に変更され、BEHAVIOR_SHOW_BARS_BY_TOUCH はDeprecatedなるため今後は使用しないほうがよくなります。

Jetpackの対応

androidx coreの1.5.0-alpha05から WindowInsetsController のバックポートである、 WindowInsetsControllerCompat が追加されています。

しかし、これを書いてる時点ではバグがあり、BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE が期待通りの挙動になりません。DeprecatedになったSYSTEM_UI_FLAG_IMMERSIVE の代わりにを使うようにドキュメントに記載されていますが、同様の挙動にはなっていないようです。

詳しくは こちらのIssue を見てください。

ドキュメント関連

WindowInsetsController のAPIドキュメントはありますが、これを書いてる時点では、ガイドはありませんでした。

古いガイドのほうは、まだ残っています。

https://developer.android.com/training/system-ui

参考

Programmer / Gamer / Google Developers Expert for Android, Kotlin / @STAR_ZERO