Если вы используете SDK 35 или более поздней версии на устройстве с Android 15 или более поздней версии, ваше приложение будет показываться от края до края. Окно занимает всю ширину и высоту экрана, а его контент отрисовывается за системными строками. К системным строкам относятся строка состояния, строка заголовка и панель навигации.
Во многих приложениях есть верхняя панель. Верхняя панель приложения должна доходить до верхнего края экрана и отображаться за строкой состояния. При прокрутке контента верхняя панель приложения может уменьшаться до высоты строки состояния.
Во многих приложениях также есть нижняя панель приложения или нижняя панель навигации. Эти панели также должны растягиваться до нижнего края экрана и отображаться за панелью навигации. В противном случае приложения должны показывать прокручиваемый контент за панелью навигации.
При реализации макета от края до края в приложении учитывайте следующее:
- Как включить отображение от края до края
- Используйте адаптивные макеты, чтобы оптимизировать интерфейс для разных типов устройств.
- Устраните визуальные наложения
- Добавьте полупрозрачные наложения за системными строками
Включить отображение от края до края
Если ваше приложение поддерживает SDK 35 или более поздней версии, режим "От края до края" автоматически включается на устройствах с Android 15 и более поздними версиями.
Чтобы включить отображение на весь экран в предыдущих версиях Android, вручную вызовите enableEdgeToEdge в onCreate вашего Activity.
Kotlin
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.enableEdgeToEdge(window)
...
}
Java
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WindowCompat.enableEdgeToEdge(getWindow());
...
}
По умолчанию enableEdgeToEdge() делает системные строки прозрачными, за исключением режима навигации с помощью трех кнопок, в котором панель навигации становится полупрозрачной. Цвета системных значков и полупрозрачного слоя зависят от того, какая тема выбрана в системе – светлая или тёмная.
Чтобы включить отображение от края до края в приложении без использования функции enableEdgeToEdge(), ознакомьтесь с разделом Как настроить отображение от края до края вручную.
Обработка перекрытий с помощью вставок
Некоторые представления приложения могут отрисовываться за системными строками, как показано на рисунке 3.
Вы можете устранить перекрытия, реагируя на вставки, которые указывают, какие части экрана пересекаются с системным пользовательским интерфейсом, например панелью навигации или строкой состояния. Пересечение может означать отображение над контентом, но оно также может информировать ваше приложение о системных жестах.
Для отображения приложения во весь экран применяются следующие типы вставок:
Отступы системных строк. Подходят для интерактивных элементов, которые не должны быть скрыты системными строками.
Отступы для вырезов на экране. Используются в областях, где из-за формы устройства может быть вырез на экране.
Отступы для системных жестов. Используются для областей навигации с помощью жестов, которые имеют приоритет над вашим приложением.
Отступы системных строк
Отступы системной строки – самый распространенный тип отступов. Они представляют собой область, в которой интерфейс системы отображается по оси Z над вашим приложением. Их лучше всего использовать для перемещения или заполнения представлений в вашем приложении, которые можно нажимать и которые не должны быть визуально скрыты системными строками.
Например, плавающая кнопка действия (FAB) на рисунке 3 частично скрыта панелью навигации.
Чтобы избежать такого визуального перекрытия в режиме жестов или кнопок, вы можете увеличить поля представления, используя getInsets(int) с WindowInsetsCompat.Type.systemBars().
В следующем примере кода показано, как реализовать отступы системной строки:
Kotlin
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 the window insets to keep passing // down to descendant views. WindowInsetsCompat.CONSUMED }
Java
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 the window insets to keep passing // down to descendant views. return WindowInsetsCompat.CONSUMED; });
Если применить это решение к примеру, показанному на рисунке 3, то в режиме кнопки визуального перекрытия не будет, как показано на рисунке 4:
То же самое относится к режиму навигации жестами, как показано на рисунке 5:
Вставки выреза на экране
На некоторых устройствах есть вырезы на экране. Обычно он находится в верхней части экрана и включен в строку состояния. Если экран устройства находится в горизонтальном режиме, вырез может быть на вертикальном краю. В зависимости от контента, который ваше приложение показывает на экране, вам следует реализовать отступы, чтобы избежать вырезов на экране, поскольку по умолчанию приложения будут рисовать в вырезе на экране.
Например, на многих экранах приложений показывается список элементов. Не закрывайте элементы списка вырезом на экране или системными строками.
Kotlin
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 }
Java
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:
Как и в случае с системными строками, вы можете избежать наложения на области системных жестов, используя getInsets(int) с WindowInsetsCompat.Type.systemGestures().
Используйте эти вставки, чтобы переместить или дополнить пролистываемые представления от краев. Чаще всего это нижние экраны, пролистывание в играх и карусели, реализованные с помощью ViewPager2.
В Android 10 и более поздних версиях ОС отступы для системных жестов включают нижний отступ для жеста перехода на главный экран, а также левый и правый отступы для жестов перехода назад.
В следующем примере кода показано, как реализовать вставки системных жестов:
Kotlin
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 }
Java
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; });
Компоненты Material Design
Многие компоненты Material Design для Android (com.google.android.material) на основе представлений автоматически обрабатывают вставки, в том числе BottomAppBar, BottomNavigationView, NavigationRailView и NavigationView.
Однако AppBarLayout не обрабатывает вставки автоматически. Добавьте android:fitsSystemWindows="true", чтобы обрабатывать верхние отступы.
Узнайте, как обрабатывать вставки с помощью компонентов Material в Compose.
Обратно совместимая отправка вставок
Чтобы остановить отправку вставок в дочерние представления и избежать чрезмерного заполнения, вы можете использовать вставки, используя константу WindowInsetsCompat.CONSUMED. Однако на устройствах с Android 10 (уровень API 29 и ниже) после вызова WindowInsetsCompat.CONSUMED отступы не передаются на соседние элементы, что может привести к непреднамеренному визуальному перекрытию.
Чтобы убедиться, что вставки отправляются на параллельные элементы во всех поддерживаемых версиях Android, используйте ViewGroupCompat#installCompatInsetsDispatch перед использованием вставок. Эта функция доступна в AndroidX Core и Core-ktx 1.16.0-alpha01 и более поздних версиях.
Kotlin
// Use the i.d. assigned to your layout's root view, e.g. R.id.main val rootView = findViewById(R.id.main) // Call before consuming insets ViewGroupCompat.installCompatInsetsDispatch(rootView)
Java
// Use the i.d. assigned to your layout's root view, e.g. R.id.main LinearLayout rootView = findViewById(R.id.main); // Call before consuming insets ViewGroupCompat.installCompatInsetsDispatch(rootView);
Режим комфортного просмотра
Некоторый контент лучше воспринимается в полноэкранном режиме, который позволяет пользователю полностью погрузиться в происходящее. Вы можете скрыть системные строки для режима погружения, используя библиотеки WindowInsetsController и WindowInsetsControllerCompat.
Kotlin
val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView) // Hide the system bars. windowInsetsController.hide(Type.systemBars()) // Show the system bars. windowInsetsController.show(Type.systemBars())
Java
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());
Подробнее о том, как скрыть системные строки в режиме погружения…
Значки в системной строке
Вызов enableEdgeToEdge гарантирует, что цвета значков системной строки обновятся при изменении темы устройства.
При переходе на показ от края до края вам может потребоваться вручную изменить цвета значков в системной строке, чтобы они контрастировали с фоном приложения. Например, чтобы создать светлые значки в строке состояния, используйте следующий код:
Kotlin
WindowCompat.getInsetsController(window, window.decorView) .isAppearanceLightStatusBars = false
Java
WindowCompat.getInsetsController(window, window.getDecorView()) .setAppearanceLightStatusBars(false);
Защита системной строки
Если ваше приложение поддерживает SDK 35 или более поздней версии, режим без полей будет включен по умолчанию.
Строка состояния и панель навигации жестами прозрачные, а панель навигации с тремя кнопками – полупрозрачная. Чтобы обеспечить обратную совместимость, вызовите enableEdgeToEdge.
Однако системные настройки по умолчанию могут подходить не для всех случаев. Чтобы определить, какие системные строки использовать – прозрачные или полупрозрачные, ознакомьтесь с руководством по дизайну системных строк Android и руководством по дизайну приложений, занимающих весь экран.
Создайте прозрачные системные строки
Чтобы сделать строку состояния прозрачной, выберите в качестве целевой версии Android 15 (SDK 35) или более позднюю или вызовите enableEdgeToEdge() с аргументами по умолчанию для более ранних версий.
Создайте прозрачную панель навигации жестами, выбрав в качестве целевой платформы Android 15 или более позднюю версию или вызвав enableEdgeToEdge() с аргументами по умолчанию для более ранних версий. Для панели навигации с тремя кнопками задайте для Window.setNavigationBarContrastEnforced значение false, иначе будет применена полупрозрачная сетка.
Как создать полупрозрачные системные строки
Чтобы создать полупрозрачную строку состояния, выполните следующие действия:
- Обновите зависимость
androidx-coreдо версии 1.16.0-beta01 или более поздней. - Оберните макет XML в
androidx.core.view.insets.ProtectionLayoutи назначьте идентификатор. - Получите программный доступ к
ProtectionLayout, чтобы настроить защиту, указав сторону иGradientProtectionдля строки состояния.
<androidx.core.view.insets.ProtectionLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/list_protection" android:layout_width="match_parent" android:layout_height="match_parent"> <ScrollView android:id="@+id/item_list" android:clipToPadding="false" android:layout_width="match_parent" android:layout_height="match_parent"> <!--items--> </ScrollView> </androidx.core.view.insets.ProtectionLayout>
findViewById<ProtectionLayout>(R.id.list_protection) .setProtections( listOf( GradientProtection( WindowInsetsCompat.Side.TOP, // Ideally, this is the pane's background color paneBackgroundColor ) ) )
Убедитесь, что значение ColorInt, переданное в GradientProtection, соответствует фону контента. Например, макет со списком и подробными сведениями, отображаемый на складном устройстве, может иметь разные GradientProtections разных цветов для панели списка и панели сведений.
Не создавайте полупрозрачную панель навигации жестами. Чтобы создать полупрозрачную панель навигации с тремя кнопками, выполните одно из следующих действий:
- Если макет уже заключен в
ProtectionView, вы можете передать дополнительныйColorProtectionилиGradientProtectionв методsetProtections. Перед этим убедитесь, чтоwindow.isNavigationBarContrastEnforced = false. - В противном случае задайте
window.isNavigationBarContrastEnforced = true.
Другие советы
Дополнительные советы по работе с вставками.
Как сделать прокручиваемый контент от края до края
Убедитесь, что последний элемент списка не скрыт системными строками в RecyclerView или NestedScrollView. Для этого настройте отступы и задайте для clipToPadding значение false.
На видео ниже показано приложение RecyclerView с отключенным (слева) и включенным (справа) режимом отображения от края до края.
Пример кода можно найти в разделе Создание динамических списков с помощью RecyclerView.
Сделайте полноэкранные диалоговые окна от края до края
Чтобы сделать полноэкранные диалоговые окна без полей, вызовите enableEdgeToEdge в Dialog.
Kotlin
class MyAlertDialogFragment : DialogFragment() {
override fun onStart(){
super.onStart()
dialog?.window?.let { WindowCompat.enableEdgeToEdge(it) }
}
...
}
Java
public class MyAlertDialogFragment extends DialogFragment {
@Override
public void onStart() {
super.onStart();
Dialog dialog = getDialog();
if (dialog != null) {
Window window = dialog.getWindow();
if (window != null) {
WindowCompat.enableEdgeToEdge(window);
}
}
}
...
}
Дополнительные ресурсы
Дополнительную информацию о полноэкранном режиме можно найти в следующих источниках:
Блоги
- Советы по обработке вставок для принудительного отображения на весь экран в Android 15
- WindowInsets – от слушателей до макетов
Проектирование
Другие документы
Видео