Поддержка вырезов на экране

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

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

Вырезы на экране поддерживаются на устройствах с 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.

Режим выреза можно задать программно или с помощью стиля в объекте activity. В примере ниже определяется стиль, который применяет к действию атрибут 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. При стандартном поведении контент приложения может отображаться в области выреза, когда системные строки видны, но не в режиме погружения. В результате контент перемещается вверх и вниз во время переходов, как показано в примере ниже.

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

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

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

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

  1. Включите режим разработчика.
  2. В разделе Для разработчиков прокрутите экран вниз до раздела Отрисовка и выберите Имитировать экран с вырезом.
  3. Выберите тип выреза.

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

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