Поддержка вырезов дисплея

Попробуйте способ создания
Jetpack Compose — рекомендуемый набор инструментов пользовательского интерфейса для Android. Узнайте, как работать с вырезами дисплея в Compose.

Вырез дисплея — это область на некоторых устройствах, которая выходит за пределы поверхности дисплея. Он обеспечивает удобство работы от края до края, обеспечивая при этом место для важных датчиков на передней панели устройства.

Android поддерживает вырезы дисплея на устройствах под управлением Android 9 (уровень API 28) и выше. Однако производители устройств также могут поддерживать вырезы дисплея на устройствах под управлением Android 8.1 или более ранней версии.

В этом документе описывается, как реализовать поддержку устройств с вырезами, в том числе как работать с областью выреза , то есть прямоугольником от края до края на поверхности дисплея, содержащим вырез.

Изображение, показывающее пример выреза дисплея вверху по центру.
Рис. 1. 1. Вырез дисплея.

Выберите, как ваше приложение будет обрабатывать области вырезов.

Если вы не хотите, чтобы ваш контент перекрывал область выреза, обычно достаточно убедиться, что ваш контент не перекрывается со строкой состояния и панелью навигации. Если вы выполняете рендеринг в области выреза, используйте WindowInsetsCompat.getDisplayCutout() для получения объекта DisplayCutout , который содержит безопасные вставки и ограничивающую рамку для каждого выреза. Эти API позволяют вам проверить, перекрывается ли ваш контент с вырезом, чтобы при необходимости можно было изменить его положение.

Вы также можете определить, расположен ли контент за областью выреза. Атрибут макета окна layoutInDisplayCutoutMode управляет тем, как содержимое отображается в области выреза. Вы можете установить layoutInDisplayCutoutMode одно из следующих значений:

  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT : контент отображается в области выреза, когда вырез дисплея содержится в системной панели. В противном случае окно не перекрывает вырез дисплея; например, контент может быть помещен в почтовый ящик при отображении в ландшафтном режиме. Если ваше приложение предназначено для SDK 35, это интерпретируется как ALWAYS для неплавающих окон.
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS : контенту всегда разрешено заходить в области выреза. Если ваше приложение предназначено для SDK 35 и работает на устройстве Android 15, это единственный разрешенный режим для неплавающих окон, обеспечивающий отображение от края до края.
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES : контент отображается в области выреза как в портретном, так и в альбомном режимах. Не используйте для плавающих окон. Если ваше приложение предназначено для SDK 35, это интерпретируется как ALWAYS для неплавающих окон.
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER : контент никогда не отображается в области выреза. Если ваше приложение предназначено для SDK 35, это интерпретируется как ALWAYS для неплавающих окон.

Вы можете установить режим выреза либо программно, либо задав стиль в своей деятельности. В следующем примере определяется стиль применения атрибута LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES к действию.

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

В следующих разделах более подробно описаны различные режимы вырезания.

Поведение по умолчанию

Если ваше приложение предназначено для SDK 35 и работает на устройстве Android 15, LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS является поведением по умолчанию, а LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT интерпретируется как LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS для неплавающих окон.

В противном случае по умолчанию используется LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT .

Рендеринг контента в областях вырезов по коротким краям

Если ваше приложение предназначено для SDK 35 и работает на устройстве Android 15, LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES интерпретируется как LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS для неплавающих окон.

С помощью LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES содержимое расширяется в область выреза на коротком крае дисплея как в книжной, так и в альбомной ориентации, независимо от того, скрыты или видимы системные панели. При использовании этого режима убедитесь, что никакой важный контент не перекрывает область выреза.

На следующем изображении показан пример LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES для устройства в портретной ориентации:

Изображение, показывающее рендеринг контента в области выреза в портретном режиме.
Рисунок 2. Рендеринг контента в области выреза в портретном режиме.

На следующем изображении показан пример LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES для устройства в альбомной ориентации:

Изображение, показывающее рендеринг контента в области выреза в ландшафтном режиме.
Рисунок 3. Рендеринг контента в области выреза в ландшафтном режиме.

В этом режиме окно расширяется под вырезами по короткому краю дисплея как в книжной, так и в альбомной ориентации, независимо от того, скрывает ли окно системные панели.

Вырез в углу считается по короткой стороне:

Изображение устройства с угловым вырезом.
Рисунок 4. Устройство с угловым вырезом.

Никогда не отображайте контент в области выреза дисплея.

Если ваше приложение предназначено для SDK 35 и работает на устройстве Android 15, LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER интерпретируется как LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS для неплавающих окон.

С помощью 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 в ландшафтном режиме.

Рекомендации по поддержке вырезов дисплея

При работе с вырезами для дисплея учитывайте следующее:

  • Помните о размещении важных элементов пользовательского интерфейса. Не позволяйте области выреза закрывать важный текст, элементы управления или другую информацию.
  • Не размещайте и не расширяйте какие-либо интерактивные элементы, требующие тонкого распознавания, в области выреза. Чувствительность к прикосновению может быть ниже в области выреза.
  • Там, где это возможно, используйте WindowInsetsCompat , чтобы получить высоту строки состояния и определить соответствующие поля для применения к вашему содержимому. Избегайте жесткого кодирования высоты строки состояния, так как это может привести к перекрытию или обрезке содержимого.

    Изображение, показывающее контент, обрезанный вверху из-за неправильной настройки вставок.
    Рисунок 7. Используйте WindowInsetsCompat чтобы избежать перекрытия или обрезки содержимого.
  • Используйте View.getLocationInWindow() чтобы определить, сколько места в окне использует ваше приложение. Не думайте, что приложение использует все окно, и не используйте View.getLocationOnScreen() .

  • Используйте режимы always , shortEdges или never Cutout, если вашему приложению необходимо переходить в режим погружения и выходить из него. Поведение выреза по умолчанию может привести к тому, что контент вашего приложения будет отображаться в области выреза, пока присутствуют системные панели, но не в режиме погружения. Это приводит к перемещению содержимого вверх и вниз во время переходов, как показано в следующем примере.

    Изображение, показывающее, как контент перемещается вверх и вниз во время переходов.
    Рисунок 8. Пример перемещения контента вверх и вниз во время переходов.
  • В режиме погружения будьте осторожны, используя координаты окна и экрана, поскольку ваше приложение не использует весь экран в почтовом ящике. Из-за почтового ящика координаты начала экрана не совпадают с координатами начала окна. При необходимости вы можете преобразовать координаты экрана в координаты представления, используя getLocationOnScreen() . На следующем изображении показано, как различаются координаты, когда содержимое находится в почтовом ящике:

    Изображение, показывающее координаты окна и экрана, когда содержимое находится в почтовом ящике.
    Рисунок 9. Координаты окна и экрана, когда контент находится в почтовом ящике.
  • При обработке MotionEvent используйте MotionEvent.getX() и MotionEvent.getY() , чтобы избежать подобных проблем с координатами. Не используйте MotionEvent.getRawX() или MotionEvent.getRawY() .

Проверьте, как отображается ваш контент

Протестируйте все экраны и возможности вашего приложения. Если есть возможность, протестируйте на устройствах с разными типами вырезов. Если у вас нет устройства с вырезом, вы можете смоделировать распространенные конфигурации выреза на любом устройстве или эмуляторе под управлением Android 9 или более поздней версии, выполнив следующие действия:

  1. Включите параметры разработчика .
  2. На экране «Параметры разработчика» прокрутите вниз до раздела «Рисование» и выберите « Имитировать дисплей с вырезом» .
  3. Выберите тип выреза.

    Изображение, показывающее, как имитировать вырез дисплея в эмуляторе.
    Рисунок 10. Параметры разработчика для проверки того, как отображается ваш контент.

Дополнительные ресурсы