ディスプレイ カットアウトとは、一部のデバイス上のディスプレイ面まで広がっている領域のことです。これにより、デバイスの前面に重要なセンサーのスペースを確保しながら、エッジ ツー エッジのエクスペリエンスを実現できます。
Android は、Android 9(API レベル 28)以降を搭載しているデバイスでディスプレイ カットアウトをサポートしています。ただし、デバイス メーカーは、Android 8.1 以前を搭載したデバイスのディスプレイ カットアウトもサポートできます。
このドキュメントでは、カットアウト領域(カットアウトを含むディスプレイ面のエッジ ツー エッジの長方形)を扱う方法など、カットアウトのあるデバイスのサポートを実装する方法について説明します。
アプリでのカットアウト領域の処理方法を選択する
コンテンツがカットアウト領域と重ならないようにしたい場合、通常はコンテンツがステータスバーやナビゲーション バーに重ならないようにするだけで十分です。カットアウト領域にレンダリングする場合は、WindowInsetsCompat.getDisplayCutout()
を使用して、各カットアウトの安全なインセットと境界ボックスを含む DisplayCutout
オブジェクトを取得します。これらの API を使用すると、コンテンツがカットアウトと重なっているかどうかを確認でき、必要に応じて位置を変更できます。
また、コンテンツがカットアウト領域の背後に配置されるかどうかも指定できます。ウィンドウ レイアウト属性 layoutInDisplayCutoutMode
は、カットアウト領域でのコンテンツの描画方法を制御します。layoutInDisplayCutoutMode
は次のいずれかの値に設定できます。
LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
: 縦表示ではコンテンツはカットアウト領域にレンダリングされますが、横表示ではレターボックス表示されます。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
の例です。
次の画像は、横向きのデバイスの LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
の例です。
このモードでは、ウィンドウがシステムバーを隠しているかどうかにかかわらず、縦向きと横向きの両方で、ウィンドウはディスプレイの短辺のカットアウトの下に広がります。
隅のカットアウトは短辺と見なされます。
コンテンツをディスプレイ カットアウト領域にレンダリングしない
LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
を使用すると、ウィンドウがカットアウト領域と重なることはありません。
縦向きの LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
の例を次に示します。
横表示の LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
の例を次に示します。
ディスプレイ カットアウトのサポートに関するベスト プラクティス
ディスプレイ カットアウトを使用する場合は、次の点を考慮してください。
- UI の重要な要素の配置に注意してください。カットアウト領域によって、重要なテキスト、コントロール、その他の情報が隠れないようにしてください。
- 細かいタップ認識が必要なインタラクティブ要素をカットアウト領域に配置または拡張しないでください。カットアウト領域では、タップの感度が低下することがあります。
可能であれば、
WindowInsetsCompat
を使用してステータスバーの高さを取得し、コンテンツに適用する適切なパディングを決定します。ステータスバーの高さをハードコードしないでください。コンテンツが重なったり、切れたりする可能性があります。View.getLocationInWindow()
を使用して、アプリが使用しているウィンドウ スペースの量を確認します。アプリがウィンドウ全体を使用しているとは限りません。また、View.getLocationOnScreen()
も使用しないでください。アプリを没入モードに移行または終了する必要がある場合は、
shortEdges
またはnever
カットアウト モードを使用します。デフォルトのカットアウト動作により、システムバーが存在するときはアプリのコンテンツがカットアウト領域にレンダリングされるものの、没入モードではアプリのコンテンツがレンダリングされないことがあります。これにより、次の例に示すように、遷移中にコンテンツが上下に移動します。没入モードでは、レターボックス表示のときにアプリは画面全体を使用しないため、ウィンドウと画面の座標を使用する際は注意が必要です。レターボックスがあるため、画面の原点からの座標はウィンドウの原点からの座標とは異なります。必要に応じて、
getLocationOnScreen()
を使用して画面の座標をビューの座標に変換できます。次の図は、コンテンツがレターボックス表示されたときの座標の違いを示しています。MotionEvent
を処理する場合は、MotionEvent.getX()
とMotionEvent.getY()
を使用して、座標に関する同様の問題を回避してください。MotionEvent.getRawX()
やMotionEvent.getRawY()
は使用しないでください。
コンテンツのレンダリング方法をテストする
アプリの画面とエクスペリエンスをすべてテストします。可能であれば、さまざまな種類のカットアウトを備えたデバイスでテストします。カットアウト付きのデバイスがない場合は、Android 9 以降を搭載したデバイスまたはエミュレータで一般的なカットアウト構成をシミュレートできます。手順は次のとおりです。
- [開発者向けオプション] を有効にします。
- [開発者向けオプション] 画面で、[描画] セクションまで下にスクロールし、[カットアウトがあるディスプレイのシミュレート] を選択します。
カットアウトのタイプを選択します。