Android 10(API レベル 29)以降の Android システムでは、完全なジェスチャーベースのナビゲーションをサポートしています。アプリでこの機能に対応するために、アプリ デベロッパーは次の 2 点を行う必要があります。
- アプリのコンテンツを画面全体に拡大する(エッジ ツー エッジへの対応)。
- 競合するアプリ ジェスチャーに対処する。
エッジ ツー エッジのアプリ コンテンツ
フローティング ナビゲーション バーによって利用できるようになった画面スペースを利用するには、アプリにいくつか変更を加える必要があります。
透明なシステムバーの設定
透明なシステムバーを設定するには、以下の値をテーマに設定します。
<!-- values-29/themes.xml: -->
<style name="AppTheme" parent="...">
<item name="android:navigationBarColor">@android:color/transparent</item>
<!-- Optional, but recommended for full edge-to-edge rendering -->
<item name="android:statusBarColor">@android:color/transparent</item>
</style>

または、Window.setNavigationBarColor()
と Window.setStatusBarColor()
を使用して動的に行うこともできます。
デバイスがジェスチャー ナビゲーションを使用するように設定されている場合、アプリのナビゲーション バーの背景を透明にすると、背後にあるコンテンツの色に基づいてハンドルの色が自動的に変更されます。 ただし、ユーザーのモードが 2 ボタンまたは 3 ボタン ナビゲーションの場合、これらのボタンの色は変わりません。代わりに、半透明の背景が適用され、ボタンが表示されたままになります。ただし、これが行われるのは、アプリが API レベル 29 以降をターゲットとする場合のみです。
UI 表示フラグの設定
ビューを画面全体にレイアウトできるようにするには、アプリでこうしたビューの処理が可能であることをアプリからシステムに伝える必要があります。そのためには、View.setSystemUiVisibility()
を使用して次のフラグを設定します。
Kotlin
view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
Java
view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
これらのフラグは、ナビゲーション バーとステータスバーが存在しないかのように、アプリを画面全体にレイアウトするようシステムに指示します。また、追加の全画面表示イベント用に SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
を設定することで、ステータスバーの背後に描画することもできます。
ステータスバーを自動的に処理するビュークラス(CoordinatorLayout
や DrawerLayout
など)を使用している場合、SYSTEM_UI_FLAG_LAYOUT_STABLE
フラグと SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
フラグがすでに設定されていることがあります。また、setSystemUiVisibility()
を使用して他のフラグ(SYSTEM_UI_FLAG_IMMERSIVE
など)を設定している場合は、それらのフラグが上述のフラグを上書きしないように注意する必要があります。
アプリがエッジ ツー エッジのビューを使用している場合でも、システムは引き続き、システムバーの場所を示すために WindowInsets
API を使用します。
手動でのインセットの使用
アプリでカスタムのビュー階層を使用する場合、システム ウィンドウのインセットを手動で使用する必要が生じることがあります。その場合は通常、OnApplyWindowInsetsListener
インターフェースを実装します。
Kotlin
view.setOnApplyWindowInsetsListener() {v, insets -> insets.consumeSystemWindowInsets()
Java
view.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() { @Override public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) { // 1. Move views on top edge down by insets.getSystemWindowInsetTop() // 2. Move views on bottom edge up by insets.getSystemWindowInsetBottom() // 3. Also check getSystemWindowInsetLeft/Right(), such as for landscape // orientations return insets.consumeSystemWindowInsets(); } });
WindowInsets
は getSystemWindowInsets()
を介して、すべてのシステムバーに通常の表示用のインセットを提供します。また、Android 10 では次のメソッドが WindowInsets
に追加されています。
getSystemGestureInsets()
: システム ジェスチャーがキャプチャされる領域のサイズを指定します。getMandatorySystemGestureInsets()
: 上のメソッドと同じですが、View.setSystemGestureExclusionRects()
がオーバーライドできない領域のみを指定します。
競合するアプリ ジェスチャーへの対処
ジェスチャー ナビゲーション モデルでは、アプリ デベロッパーが以前に使用していたジェスチャーと競合することがあります。そのため、アプリのユーザー インターフェースの調整が必要になることがあります。
「戻る」ジェスチャーとの競合
「戻る」の新しいシステム ジェスチャーは、画面の左または右端から内側へのスワイプです。このジェスチャーが、これらの領域内におけるアプリのナビゲーション要素を妨げる可能性があります。画面の左端および右端でのナビゲーション要素の機能を維持するには、タップ入力を受け入れる必要がある領域をシステムに示すことで、「戻る」ジェスチャーを選択的に無効にする必要があります。これを行うには、Android 10 で導入された View.setSystemGestureExclusionRects()
API に List<Rect>
を渡します。このメソッドは、androidx.core:core:1.1.0-dev01
以降の ViewCompat
でも利用できます。
次に例を示します。
Kotlin
var exclusionRects = listOf(rect1, rect2, rect3) fun onLayout( changedCanvas: Boolean, left: Int, top: Int, right: Int, bottom: Int) { // Update rect bounds and the exclusionRects list setSystemGestureExclusionRects(exclusionRects) } fun onDraw(canvas: Canvas) { // Update rect bounds and the exclusionRects list setSystemGestureExclusionRects(exclusionRects) }
Java
List<Rect> exclusionRects; public void onLayout( boolean changedCanvas, int left, int top, int right, int bottom) { // Update rect bounds and the exclusionRects list setSystemGestureExclusionRects(exclusionRects); } public void onDraw(Canvas canvas) { // Update rect bounds and the exclusionRects list setSystemGestureExclusionRects(exclusionRects); }
ホーム ジェスチャーおよびクイック スイッチ ジェスチャーとの競合
ホームとクイック スイッチの新しいシステム ジェスチャーは、以前はナビゲーション バーが表示されていた画面下部のスペースでのスワイプです。アプリは、これらのジェスチャーを「戻る」ジェスチャーのように無効にすることはできません。
この問題を軽減するために、Android 10 では、タッチ認識のしきい値をアプリに通知する WindowInsets.getMandatorySystemGestureInsets()
API が導入されています。
ビュー階層のないゲームやアプリ
ビュー階層のないゲームなどのアプリでは、多くの場合、ユーザーはシステム ジェスチャー領域の近くをスワイプする必要があります。この場合、ゲームは Window.setSystemGestureExclusionRects()
を使用して、システム ジェスチャー領域に重なる領域を除外することができます。ゲームプレイ中など、必要なときのみこうした領域を除外するように注意する必要があります。
ゲームでユーザーがホーム ジェスチャー領域の近くをスワイプする必要があれば、アプリは没入モードで配置するようにリクエストできます。これによって、ゲームの操作中はシステム ジェスチャーが無効になりますが、ユーザーは画面を下からスワイプすることで、システム ジェスチャーを再度有効にすることができます。
参考情報
ジェスチャー ナビゲーションについて詳しくは、以下の参考情報をご確認ください。