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

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_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.コンテンツのレンダリングをテストするための開発者向けオプション。

参考情報