ディスプレイ カットアウトのサポート

ディスプレイ カットアウト付きのデバイス

ディスプレイ カットアウトとは、一部のデバイスにある表示サーフェスに拡張された領域です。ディスプレイ カットアウトにより、デバイスの前面に重要なセンサーのスペースを確保しながら、エッジ ツー エッジのエクスペリエンスを実現できます。Android 9(API レベル 28)以降を搭載したデバイスでは、ディスプレイ カットアウトが公式にサポートされています。Android 8.1 以前が搭載されているデバイスでも、デバイス メーカーがディスプレイ カットアウトをサポートしている場合があります。

このトピックでは、カットアウト領域(カットアウトを含む表示サーフェスの長方形全体)の活用方法など、カットアウト付きのデバイスに対するサポートの実装方法について説明します。

ディスプレイ カットアウト付きのデバイスに期待できること

Android 9 が搭載されているデバイスでは、整合性とアプリの互換性を維持するために、以下のカットアウト様式に従う必要があります。

  • 1 つの辺に最大で 1 つのカットアウトを含めることができる。
  • デバイスに 3 つ以上のカットアウトを含めることはできない。
  • デバイスの長辺にカットアウトを含めることはできない。
  • 特別なフラグが設定されていない縦向き表示の場合、ステータスバーを少なくともカットアウトの高さまで拡張する必要がある。
  • 全画面表示または横向き表示の場合、デフォルトでカットアウト領域全体をレターボックス表示する必要がある。

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

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

Android では、カットアウト領域内にコンテンツを表示するかどうかを制御することもできます。ウィンドウのレイアウト属性 layoutInDisplayCutoutMode を使用すると、カットアウト領域内でのコンテンツの描画方法を制御できます。layoutInDisplayCutoutMode は次のいずれかの値に設定できます。

カットアウトのモードを設定するには、プログラムを使用するか、アクティビティでスタイルを設定します。次の例では、LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES 属性をアクティビティに適用するために使用可能なスタイルを定義しています。

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

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

デフォルトの動作

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

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

動画、写真、マップ、ゲームなどの一部のコンテンツは、カットアウト領域にレンダリングすることで、臨場感あふれるエッジ ツー エッジのエクスペリエンスをユーザーに提供できます。LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES を使用すると、システムバーが表示されているかどうかに関係なく、縦向きと横向きのどちらでも、ディスプレイの短い辺のカットアウト領域にコンテンツを拡張できます。画面の長い辺のカットアウト領域にウィンドウを拡張することはできません。このモードを使用する場合は、重要なコンテンツがカットアウト領域と重ならないようにしてください。

Android では、コンテンツ ビューをシステムバーと重ねることができない場合があります。この動作をオーバーライドして、コンテンツをカットアウト領域に強制的に拡張するには、View.setSystemUiVisibility(int) メソッドで以下のフラグのいずれかをビューの表示に適用します。

  • SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
  • SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
  • SYSTEM_UI_FLAG_LAYOUT_STABLE

以下に、LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES の例をいくつか示します。

縦向きモードでのカットアウト領域へのコンテンツのレンダリング

横向きモードでのカットアウト領域へのコンテンツのレンダリング

画面隅のカットアウトは短い辺の上とみなされるため、同じ動作が適用されます。

画面隅のカットアウト付きのデバイス

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

LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER を使用すると、ウィンドウをカットアウト領域と重ねることができなくなります。

このモードは、View.SYSTEM_UI_FLAG_FULLSCREEN または View.SYSTEM_UI_FLAG_HIDE_NAVIGATION を一時的に設定するウィンドウとともに使用して、フラグが設定またはクリアされたときにウィンドウの別のレイアウトが実行されないようにする必要があります。

以下に、LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER の例を示します。

特殊モード

Android 8.1(API レベル 27)以前が搭載されているデバイスの一部は、特殊モードをサポートしています。ユーザーはこのモードを使用して、レターボックス表示された全画面または横向き表示のアプリをカットアウト領域に拡張することができます。このモードは通常、画面を拡張する前に確認を求めるダイアログを表示するナビゲーション バーでの切り替えによって制御されます。

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

ディスプレイ カットアウト付きのデバイスでは、以下の点を考慮してください。

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

  • アプリがウィンドウ全体に表示されると決めつけないでください。代わりに、View.getLocationInWindow() を使用してアプリの場所を確認します。View.getLocationOnScreen() は使用しないでください。

  • 全画面モードへの遷移または全画面モードからの遷移を適切に処理してください。詳しくは、こちらの Android デベロッパー ブログの投稿をご覧ください。

  • 縦向きモードのデフォルトのカットアウト動作では、カットアウト領域が上端にあり、ウィンドウで FLAG_FULLSCREEN または View.SYSTEM_UI_FLAG_FULLSCREEN を設定していない場合、ウィンドウはカットアウト領域に拡張できます。同様に、カットアウト領域が下端にあり、ウィンドウで View.SYSTEM_UI_FLAG_HIDE_NAVIGATION を設定していない場合、ウィンドウはカットアウト領域に拡張できます。全画面または横向きモードでは、ウィンドウがカットアウト領域と重ならないようにレイアウトされます。

  • アプリで全画面モードに遷移するか、全画面モードから遷移する場合は、shortEdges または never カットアウト モードを使用します。デフォルトのカットアウト動作では、次の図に示すように、モードの遷移中にアプリのコンテンツが上下に移動することがあります。

  • 全画面モードでは、アプリがレターボックス表示されると画面全体に表示されなくなるため、ウィンドウと画面の座標を使用する際には注意してください。レターボックス表示が原因で、画面の原点からの座標がウィンドウの原点からの座標と同じにならなくなります。画面の座標は、getLocationOnScreen() を使用して、必要に応じてビューの座標に変換することができます。次の図は、コンテンツがレターボックス表示されたときの座標の違いを示しています。

    MotionEvent を処理する場合は、MotionEvent.getX()MotionEvent.getY() を使用して、座標に関する同様の問題が起きないようにしてください。MotionEvent.getRawX() または MotionEvent.getRawY() は使用しないでください。

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

エミュレータでのディスプレイ カットアウトのシミュレーション

アプリの画面と動作をすべてテストしてください。可能な場合は、カットアウトのタイプが異なる各種デバイスでテストを実施します。カットアウト付きのデバイスがない場合は、Android 9 が搭載されているデバイスまたはエミュレータで、次の手順を使用して一般的なカットアウト構成をシミュレートできます。

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

参考リンク

ディスプレイ カットアウトのサポートについて詳しくは、以下のリンクをご覧ください。