Отображение контента от края до края в вашем приложении

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

Как только вы настроите SDK 35 или более позднюю версию на устройстве под управлением Android 15 или более поздней версии, ваше приложение будет отображаться без ограничений. Окно занимает всю ширину и высоту дисплея, располагаясь за системными полосами. Системные панели включают строку состояния, строку заголовка и панель навигации.

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

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

Рисунок 1. Системные панели в макете от края до края.

При реализации сквозного макета в вашем приложении имейте в виду следующее:

  1. Включить отображение от края до края
  2. Устраните любые визуальные перекрытия.
  3. Рассмотрите возможность показа скримов за системными панелями.
пример изображения за строкой состояния
Рисунок 2. Пример изображения за строкой состояния.

Включить отображение от края до края

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

Чтобы включить сквозную технологию в предыдущих версиях Android, выполните следующие действия:

  1. Добавьте зависимость к библиотеке androidx.activity в файле build.gradle вашего приложения или модуля:

    Котлин

    dependencies {
        val activity_version = activity_version
        // Java language implementation
        implementation("androidx.activity:activity:$activity_version")
        // Kotlin
        implementation("androidx.activity:activity-ktx:$activity_version")
    }

    классный

    dependencies {
        def activity_version = activity_version
        // Java language implementation
        implementation 'androidx.activity:activity:$activity_version'
        // Kotlin
        implementation 'androidx.activity:activity-ktx:$activity_version'
    }
  2. Импортируйте функцию расширения enableEdgeToEdge в свое приложение:

Включите сквозное соединение вручную, вызвав enableEdgeToEdge в onCreate вашего Activity . Его следует вызывать перед setContentView .

Котлин

     override fun onCreate(savedInstanceState: Bundle?) {
       enableEdgeToEdge()
       super.onCreate(savedInstanceState)
       ...
     }
   

Ява

     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
       EdgeToEdge.enable(this);
       super.onCreate(savedInstanceState);
       ...
     }
   

По умолчанию enableEdgeToEdge() делает системные панели прозрачными, за исключением режима навигации с тремя кнопками, где строка состояния становится полупрозрачной. Цвета системных значков и экрана настраиваются в зависимости от светлой или темной темы системы.

Функция enableEdgeToEdge() автоматически объявляет, что приложение должно располагаться от края до края, и настраивает цвета системных полос.

Чтобы включить безрамочное отображение в приложении без использования функции enableEdgeToEdge() , см. раздел Настройка безрамочного отображения вручную .

Обработка перекрытий с помощью вставок

Некоторые представления вашего приложения могут находиться за системными панелями, как показано на рисунке 3.

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

Типы вставок, которые применяются для отображения вашего приложения от края до края:

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

  • Вставки для выреза дисплея: для мест, где из-за формы устройства может быть вырез экрана.

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

Вставки в системные стержни

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

Например, кнопка плавающего действия (FAB) на рис. 3 частично скрыта панелью навигации:

пример реализации от края до края, но панель навигации закрывает FAB
Рисунок 3. Панель навигации, перекрывающая FAB в макете от края до края.

Чтобы избежать такого рода визуального перекрытия в режиме жестов или в режиме кнопок, вы можете увеличить поля представления, используя getInsets(int) с WindowInsetsCompat.Type.systemBars() .

В следующем примере кода показано, как реализовать вставки системной панели:

Котлин

ViewCompat.setOnApplyWindowInsetsListener(fab) { v, windowInsets ->
  val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
  // Apply the insets as a margin to the view. This solution sets
  // only the bottom, left, and right dimensions, but you can apply whichever
  // insets are appropriate to your layout. You can also update the view padding
  // if that's more appropriate.
  v.updateLayoutParams<MarginLayoutParams> {
      leftMargin = insets.left,
      bottomMargin = insets.bottom,
      rightMargin = insets.right,
  }

  // Return CONSUMED if you don't want want the window insets to keep passing
  // down to descendant views.
  WindowInsetsCompat.CONSUMED
}

Ява

ViewCompat.setOnApplyWindowInsetsListener(fab, (v, windowInsets) -> {
  Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
  // Apply the insets as a margin to the view. This solution sets only the
  // bottom, left, and right dimensions, but you can apply whichever insets are
  // appropriate to your layout. You can also update the view padding if that's
  // more appropriate.
  MarginLayoutParams mlp = (MarginLayoutParams) v.getLayoutParams();
  mlp.leftMargin = insets.left;
  mlp.bottomMargin = insets.bottom;
  mlp.rightMargin = insets.right;
  v.setLayoutParams(mlp);

  // Return CONSUMED if you don't want want the window insets to keep passing
  // down to descendant views.
    return WindowInsetsCompat.CONSUMED;
});

Если вы примените это решение к примеру, показанному на рисунке 3, это приведет к отсутствию визуального перекрытия в режиме кнопки, как показано на рисунке 4:

полупрозрачная панель навигации, не закрывающая FAB
Рисунок 4. Устранение визуального перекрытия в режиме кнопки.

То же самое относится и к режиму навигации с помощью жестов, как показано на рисунке 5:

от края до края с навигацией жестами
Рисунок 5. Устранение визуального перекрытия в режиме навигации с помощью жестов.

Вставки для вырезов дисплея

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

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

Котлин

ViewCompat.setOnApplyWindowInsetsListener(binding.recyclerView) { v, insets ->
  val bars = insets.getInsets(
    WindowInsetsCompat.Type.systemBars()
      or WindowInsetsCompat.Type.displayCutout()
  )
  v.updatePadding(
    left = bars.left,
    top = bars.top,
    right = bars.right,
    bottom = bars.bottom,
  )
  WindowInsetsCompat.CONSUMED
}

Ява

ViewCompat.setOnApplyWindowInsetsListener(mBinding.recyclerView, (v, insets) -> {
  Insets bars = insets.getInsets(
    WindowInsetsCompat.Type.systemBars()
    | WindowInsetsCompat.Type.displayCutout()
  );
  v.setPadding(bars.left, bars.top, bars.right, bars.bottom);
  return WindowInsetsCompat.CONSUMED;
});

Определите значение WindowInsetsCompat , взяв логическое значение или из системных полос и типов вырезов дисплея.

Установите для clipToPadding значение RecyclerView , чтобы заполнение прокручивалось вместе с элементами списка. Это позволяет элементам выходить за системные панели при прокрутке пользователем, как показано в следующем примере.

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipToPadding="false"
    app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

Вставки системных жестов

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

Пример вставок системных жестов
Рисунок 6. Вставки системных жестов.

Как и вставки системной панели, вы можете избежать перекрытия вставок системных жестов, используя getInsets(int) с WindowInsetsCompat.Type.systemGestures() .

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

В Android 10 или более поздней версии системные вставки жестов содержат нижнюю вставку для жеста «Домой», а также левую и правую вставку для жестов «Назад»:

пример измерений вставки системных жестов
Рисунок 7. Измерения вставки системных жестов.

В следующем примере кода показано, как реализовать вставки системных жестов:

Котлин

ViewCompat.setOnApplyWindowInsetsListener(view) { view, windowInsets ->
    val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures())
    // Apply the insets as padding to the view. Here, set all the dimensions
    // as appropriate to your layout. You can also update the view's margin if
    // more appropriate.
    view.updatePadding(insets.left, insets.top, insets.right, insets.bottom)

    // Return CONSUMED if you don't want the window insets to keep passing down
    // to descendant views.
    WindowInsetsCompat.CONSUMED
}

Ява

ViewCompat.setOnApplyWindowInsetsListener(view, (v, windowInsets) -> {
    Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures());
    // Apply the insets as padding to the view. Here, set all the dimensions
    // as appropriate to your layout. You can also update the view's margin if
    // more appropriate.
    view.setPadding(insets.left, insets.top, insets.right, insets.bottom);

    // Return CONSUMED if you don't want the window insets to keep passing down
    // to descendant views.
    return WindowInsetsCompat.CONSUMED;
});

Материальные компоненты

Многие материальные компоненты Android на основе представлений (com.google.android.material){:.external} автоматически обрабатывают вставки, включая BottomAppBar , BottomNavigationView , NavigationRailView и NavigationView

Однако AppBarLayout не обрабатывает вставки автоматически. Добавьте android:fitsSystemWindows="true" для обработки верхних вставок.

Прочтите, как обрабатывать вставки с помощью компонентов материала в Compose .

Режим погружения

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

Котлин

val windowInsetsController =
      WindowCompat.getInsetsController(window, window.decorView)

// Hide the system bars.
windowInsetsController.hide(Type.systemBars())

// Show the system bars.
windowInsetsController.show(Type.systemBars())

Ява

Window window = getWindow();
WindowInsetsControllerCompat windowInsetsController =
      WindowCompat.getInsetsController(window, window.getDecorView());
if (windowInsetsController == null) {
    return;
  }
// Hide the system bars.
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars());

// Show the system bars.
windowInsetsController.show(WindowInsetsCompat.Type.systemBars());

Дополнительные сведения о реализации этой функции см. в разделе Скрытие системных панелей для режима погружения .

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

Дополнительные сведения о WindowInsets , навигации с помощью жестов и работе вставок см. в следующих ссылках: