ディスプレイ カットアウトをサポートする

Compose を試す
Jetpack Compose は、Android に推奨される UI ツールキットです。Compose でディスプレイ カットアウトを操作する方法について学習します。

一部のデバイスでは、ディスプレイ カットアウトはディスプレイ サーフェスまで広がる領域です。デバイスの前面に重要なセンサー用のスペースを確保しながら、エッジ ツー エッジのエクスペリエンスを実現します。

Android は、Android 9(API レベル 28)以降を搭載しているデバイスでディスプレイ カットアウトをサポートします。ただし、デバイス メーカーは、Android 8.1 以前を搭載しているデバイスでディスプレイ カットアウトをサポートすることもできます。

このドキュメントでは、カットアウト領域(カットアウトを含むディスプレイ サーフェス上の端から端までの長方形)の操作方法など、カットアウトのあるデバイスのサポートを実装する方法について説明します。

上部中央のディスプレイ カットアウトの例を示す画像
図 1. 1 ディスプレイ カットアウト。

アプリでのカットアウト領域の処理方法を選択する

コンテンツがカットアウト領域に重ならないようにするには、通常、コンテンツがステータスバーやナビゲーション バーと重ならないようにすれば十分です。カットアウト領域にレンダリングする場合は、WindowInsetsCompat.getDisplayCutout() を使用して、各カットアウトの安全なインセットと境界ボックスを含む DisplayCutout オブジェクトを取得します。これらの API を使用すると、コンテンツがカットアウトと重なっているかどうかを確認できるため、必要に応じて配置を変更できます。

また、コンテンツがカットアウト領域の背後に配置されるかどうかも指定できます。layoutInDisplayCutoutMode ウィンドウ レイアウト属性は、カットアウト領域にコンテンツを描画する方法を制御します。layoutInDisplayCutoutMode は次のいずれかの値に設定できます。

  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS: コンテンツを常にカットアウト領域に拡張できます。これは、Android 15 以降を搭載したデバイスのデフォルト モードです。
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES: 縦向きと横向きの両方で、コンテンツがカットアウト領域にレンダリングされます。フローティング ウィンドウには使用しないでください。
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER: コンテンツがカットアウト領域にレンダリングされることはありません。

カットアウト モードは、プログラムで設定することも、アクティビティでスタイルを設定して設定することもできます。以下の例では、LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES 属性をアクティビティに適用するスタイルを定義しています。

<style name="ActivityTheme">
  <item name="android:windowLayoutInDisplayCutoutMode">
    shortEdges <!-- default, shortEdges, or never -->
  </item>
</style>

以降のセクションでは、さまざまなカットアウト モードについて詳しく説明します。

デフォルトの動作

特別なフラグが設定されていない縦向きのデフォルトでは、カットアウトがあるデバイスのステータスバーはカットアウトと同じ高さにサイズ変更され、コンテンツはその下の領域に表示されます。横向きまたは全画面モードでは、アプリ ウィンドウがレターボックス表示され、コンテンツがカットアウト領域に表示されません。

短い辺のカットアウト領域にコンテンツをレンダリングする

動画、写真、地図、ゲームなどのコンテンツでは、カットアウト領域でレンダリングすると、より没入感のあるエッジ ツー エッジのエクスペリエンスを提供できます。LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES を使用すると、コンテンツは縦向きと横向きの両方で、システムバーが非表示か表示されているかにかかわらず、ディスプレイの短辺のカットアウト領域にまで広がります。このモードを使用する場合は、重要なコンテンツがカットアウト領域と重ならないようにしてください。

次の図は、縦向きのデバイスの LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES の例です。

ポートレート モードで、コンテンツがカットアウト領域にレンダリングされている様子を示す画像
図 2. ポートレート モードでのカットアウト領域へのコンテンツのレンダリング。

次の図は、横向きデバイスの LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES の例です。

横表示でカットアウト領域にコンテンツがレンダリングされる様子を示す画像
図 3. 横表示でのカットアウト領域へのコンテンツのレンダリング。

このモードでは、ウィンドウがシステムバーを非表示にしているかどうかにかかわらず、縦向きと横向きの両方で、ディスプレイの短辺のカットアウトの下にウィンドウが拡張されます。

隅のカットアウトは短辺にあるとみなされます。

隅にカットアウトがあるデバイスの画像
図 4. 隅にカットアウトがあるデバイス。

コンテンツをディスプレイ カットアウト領域にレンダリングしない

LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER では、ウィンドウがカットアウト領域と重なることはありません。

縦向きの LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER の例を次に示します。

縦向きの LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER を示す画像
図 5.ポートレート モードの LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER の例。

横向きモードの LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER の例を次に示します。

横向きの LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER を示す画像
図 6.横表示の LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER の例。

ディスプレイ カットアウトのサポートに関するベスト プラクティス

ディスプレイ カットアウトを使用する場合は、次の点を考慮してください。

  • UI の重要な要素の配置に注意してください。カットアウト領域によって重要なテキスト、コントロール、その他の情報が隠れないようにしてください。
  • きめ細かい認識が必要なインタラクティブ要素をカットアウト領域に配置または拡張しないでください。カットアウト領域では、タップの感度が低くなる場合があります。
  • 可能であれば、WindowInsetsCompat を使用してステータスバーの高さを取得し、コンテンツに適用する適切なパディングを決定します。ステータスバーの高さをハードコードしないようにしてください。ハードコードすると、コンテンツが重なったり、切り取られたりすることがあります。

    インセットが不適切に設定されているために上部が切り取られたコンテンツを示す画像
    図 7.コンテンツが重なったり、切り取られたりしないように、WindowInsetsCompat を使用します。
  • View.getLocationInWindow() を使用して、アプリが使用しているウィンドウ領域の量を確認します。アプリがウィンドウ全体を使用しているとは想定せず、View.getLocationOnScreen() も使用しません。

  • アプリを没入モードに切り替える、または没入モードから切り替える必要がある場合は、shortEdges または never カットアウト モードを使用します。デフォルトのカットアウト動作では、システムバーが存在する場合はアプリのコンテンツがカットアウト領域にレンダリングされますが、没入モードでは表示されない場合があります。これにより、次の例に示すように、遷移中にコンテンツが上下に移動します。

    遷移中にコンテンツが上下する様子を示す画像。
    図 8.遷移中にコンテンツが上下する例。
  • 没入モードでは、ウィンドウ座標と画面座標を使用する際は注意が必要です。アプリでレターボックス表示を行うと、画面全体が使用されないためです。レターボックス表示のため、画面の原点からの座標はウィンドウの原点からの座標とは異なります。必要に応じて、getLocationOnScreen() を使用して画面座標をビュー座標に変換できます。次の図は、コンテンツがレターボックス表示されるときの座標の違いを示しています。

    コンテンツがレターボックス表示されるときのウィンドウと画面の座標を示す画像。
    図 9.コンテンツがレターボックス表示されるときのウィンドウ座標と画面座標。
  • MotionEvent を処理する際は、MotionEvent.getX()MotionEvent.getY() を使用して、同様の座標の問題が発生しないようにしてください。MotionEvent.getRawX()MotionEvent.getRawY() は使用しないでください。

コンテンツのレンダリング方法をテストする

アプリの画面とエクスペリエンスのすべてをテストします。可能であれば、さまざまな種類のカットアウトを持つデバイスでテストします。カットアウトのあるデバイスがない場合は、次の手順に沿って、Android 9 以降を搭載したデバイスまたはエミュレータで一般的なカットアウト構成をシミュレートできます。

  1. [開発者向けオプション] を有効にします。
  2. [開発者向けオプション] 画面で [描画] セクションまで下にスクロールし、[カットアウトでディスプレイをシミュレート] を選択します。
  3. カットアウトのタイプを選択します。

    エミュレータでディスプレイ カットアウトをシミュレートする方法を示す画像
    図 10.コンテンツがどのようにレンダリングされるかをテストするための開発者向けオプション。

参考情報