システムバーの背後に描画することで、ディスプレイの幅と高さ全体を使用してアプリのエッジ ツー エッジを表示できます。システムバーは、ステータスバーとナビゲーション バーです。
エッジ ツー エッジのレイアウトを実装するには、アプリで次のことを行う必要があります。
- ナビゲーション バーの背後に描画して、より魅力的でモダンなユーザー エクスペリエンスを実現します。
- 全幅画像の場合など、コンテンツとレイアウトに適している場合は、ステータスバーの背後に描画します。そのためには、画面上部に固定されるアプリバーを定義する
AppBarLayout
などの API を使用します。
アプリにエッジ ツー エッジのレイアウトを実装する手順は次のとおりです。
- 狭額縁ディスプレイを有効にする。
- 視覚的な重なりがあれば対処します。
狭額縁ディスプレイを有効にする。
アプリでエッジ ツー エッジ ディスプレイを有効にするには、Activity
の onCreate
で enableEdgeToEdge
を呼び出します。setContentView
の前に呼び出す必要があります。
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { enableEdgeToEdge() super.onCreate(savedInstanceState) ... }
Java
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { EdgeToEdge.enable(this); super.onCreate(savedInstanceState); ... }
デフォルトでは、enableEdgeToEdge
はシステムバーを透明にします。ただし、3 ボタン ナビゲーション モードでは、ステータスバーに半透明のスクリムが表示されます。システム アイコンとスクリムの色は、システムのライトモードまたはダークモードに基づいて調整されます。
enableEdgeToEdge
メソッドは、アプリを端から端までレイアウトする必要があることを自動的に宣言し、システムバーの色を調整します。なんらかの理由でエッジ ツー エッジ ディスプレイを手動でセットアップする必要がある場合は、エッジ ツー エッジ ディスプレイを手動でセットアップするをご覧ください。
インセットを使用して重複を処理する
エッジ ツー エッジ ディスプレイを有効にすると、図 3 に示すように、アプリのビューの一部がシステムバーの背後に描画されることがあります。
画面のどの部分がナビゲーション バーやステータスバーなどのシステム UI と交差するかを指定するインセットに反応することで、重複に対処できます。交差とは、コンテンツの上に表示されることを意味しますが、アプリにシステム ジェスチャーを通知することもできます。
アプリのエッジ ツー エッジ表示に適用されるインセットのタイプは次のとおりです。
システムバー インセット: タップ可能で、システムバーによって視覚的に隠してはならないビューに最適です。
システム ジェスチャー インセット: アプリよりも優先される、システムが使用するジェスチャー ナビゲーション領域に使用します。
システムバー インセット
システムバー インセットは、最も一般的なタイプのインセットです。これは、システム UI がアプリの上の Z 軸に表示される領域を表します。タップ可能で、システムバーで視覚的に隠してはならないアプリ内のビューを移動またはパディングするのに最適です。
たとえば、図 3 のフローティング アクション ボタン(FAB)は、ナビゲーション バーによって部分的に覆われています。
ジェスチャー モードとボタンモードのどちらでも、このような視覚的な重なりを防ぐには、getInsets(int)
と WindowInsetsCompat.Type.systemBars()
を使用してビューのマージンを大きくします。
次のコード例は、システムバー インセットを実装する方法を示しています。
Kotlin
ViewCompat.setOnApplyWindowInsetsListener(fab) { v, windowInsets -> val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) // Apply the insets as a margin to the view. This solution sets // only the bottom, left, and right dimensions, but you can apply whichever // insets are appropriate to your layout. You can also update the view padding // if that's more appropriate. v.updateLayoutParams<MarginLayoutParams>( leftMargin = insets.left, bottomMargin = insets.bottom, rightMargin = insets.right, ) // Return CONSUMED if you don't want want the window insets to keep passing // down to descendant views. WindowInsetsCompat.CONSUMED }
Java
ViewCompat.setOnApplyWindowInsetsListener(fab, (v, windowInsets) -> { Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()); // Apply the insets as a margin to the view. This solution sets only the // bottom, left, and right dimensions, but you can apply whichever insets are // appropriate to your layout. You can also update the view padding if that's // more appropriate. MarginLayoutParams mlp = (MarginLayoutParams) v.getLayoutParams(); mlp.leftMargin = insets.left; mlp.bottomMargin = insets.bottom; mlp.rightMargin = insets.right; v.setLayoutParams(mlp); // Return CONSUMED if you don't want want the window insets to keep passing // down to descendant views. return WindowInsetsCompat.CONSUMED; });
この解決策を図 3 の例に適用すると、図 4 に示すように、ボタンモードで視覚的な重なりは発生しません。
ジェスチャー ナビゲーション モードについても同様です(図 5 を参照)。
システム ジェスチャー インセット
システム ジェスチャー インセットは、ウィンドウ内でシステム ジェスチャーがアプリよりも優先される領域を表します。これらの領域は、図 6 でオレンジ色で示されています。
システムバー インセットと同様に、getInsets(int)
と WindowInsetsCompat.Type.systemGestures()
を使用すると、システム ジェスチャー インセットの重複を回避できます。
このインセットを使用すると、スワイプ可能なビューを端から離れるように移動したり、パディングしたりできます。一般的なユースケースには、ボトムシート、ゲーム内のスワイプ、ViewPager2
を使用して実装されたカルーセルなどがあります。
Android 10 以降では、システム ジェスチャー インセットには、ホーム ジェスチャー用の下部インセットと、「戻る」ジェスチャー用の左右のインセットが含まれています。
次のコード例は、システム ジェスチャー インセットを実装する方法を示しています。
Kotlin
ViewCompat.setOnApplyWindowInsetsListener(view) { view, windowInsets -> val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures()) // Apply the insets as padding to the view. Here, set all the dimensions // as appropriate to your layout. You can also update the view's margin if // more appropriate. view.updatePadding(insets.left, insets.top, insets.right, insets.bottom) // Return CONSUMED if you don't want the window insets to keep passing down // to descendant views. WindowInsetsCompat.CONSUMED }
Java
ViewCompat.setOnApplyWindowInsetsListener(view, (v, windowInsets) -> { Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures()); // Apply the insets as padding to the view. Here, set all the dimensions // as appropriate to your layout. You can also update the view's margin if // more appropriate. view.setPadding(insets.left, insets.top, insets.right, insets.bottom); // Return CONSUMED if you don't want the window insets to keep passing down // to descendant views. return WindowInsetsCompat.CONSUMED; });
没入モード
コンテンツによっては全画面表示が推奨され、ユーザーの没入感が高まります。没入モードのシステムバーを非表示にするには、WindowInsetsController
ライブラリと WindowInsetsControllerCompat
ライブラリを使用します。
Kotlin
val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView) // Hide the system bars. windowInsetsController.hide(Type.systemBars()) // Show the system bars. windowInsetsController.show(Type.systemBars())
Java
Window window = getWindow(); WindowInsetsControllerCompat windowInsetsController = WindowCompat.getInsetsController(window, window.getDecorView()); if (windowInsetsController == null) { return; } // Hide the system bars. windowInsetsController.hide(WindowInsetsCompat.Type.systemBars()); // Show the system bars. windowInsetsController.show(WindowInsetsCompat.Type.systemBars());
この機能の実装について詳しくは、没入モードのシステムバーを非表示にするをご覧ください。
参考情報
WindowInsets
、ジェスチャー ナビゲーション、インセットの仕組みについて詳しくは、以下のリファレンスをご覧ください。