Показываем, что такое Safe Area — безопасная зона экрана, гарантирующая, что контент не перекрывается системными элементами: notch, Dynamic Island, StatusBar, индикатором Home и скруглёнными углами. Safe Area — обязательный элемент адаптивной вёрстки в iOS и Android, без которого интерфейс может выглядеть некорректно на устройствах с вырезами. По данным Apple HIG (2025), с момента появления iPhone X в 2017 году все приложения обязаны использовать Safe Area Layout Guide.
Главное
Safe Area — это прямоугольная область экрана, в которой контент гарантированно не перекрывается аппаратными и программными системными элементами: вырезом камеры (notch), Dynamic Island, строкой состояния (StatusBar), индикатором жестовой навигации (Home Indicator), скруглёнными углами дисплея и панелью навигации. Границы Safe Area динамически меняются при повороте устройства, вызове клавиатуры или запуске Split View. По данным Apple Human Interface Guidelines (2025), игнорирование Safe Area считается ошибкой дизайна и может привести к отклонению приложения при ревью.
Safe Area решает проблему фрагментации экранов в мобильной экосистеме. До iPhone X все iPhone имели прямоугольный дисплей с одинаковыми пропорциями. С появлением notch количество вариантов экранов выросло до 20+ — разные размеры ноутчей, Dynamic Island, скругления, индикаторы. Safe Area абстрагирует разработчика от этих различий, предоставляя единый API для адаптивных отступов. По данным Apple Developer (2025), iOS автоматически применяет Safe Area для корневого view, но для UICollectionView и UIScrollView требуется ручная настройка.
| Устройство | Тип выреза | Верхний отступ | Нижний отступ | StatusBar |
|---|---|---|---|---|
| iPhone SE (3rd gen) | Нет | 20px | 0px | Есть |
| iPhone 13 Pro | Notch | 47px | 34px | Внутри notch |
| iPhone 14 Pro | Dynamic Island | 59px | 34px | Внутри DI |
| iPhone 16 Pro | Dynamic Island | 59px | 34px | Внутри DI |
| Android Pixel 8 | Punch-hole (камера) | 24px | 24px | Статус бар |
В iOS Safe Area реализован через SafeAreaLayoutGuide в UIKit и модификатор safeAreaInset в SwiftUI. SafeAreaLayoutGuide — это layout guide, который добавляется к каждому UIView и определяет прямоугольник, свободный от системных элементов. В Interface Builder Safe Area отображается в виде голубой области. SwiftUI применяет Safe Area автоматически для большинства контейнеров, но позволяет игнорировать её через .ignoresSafeArea().
// UIKit: SafeAreaLayoutGuide
let safeGuide = view.safeAreaLayoutGuide
button.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
button.topAnchor.constraint(
equalTo: safeGuide.topAnchor),
button.leadingAnchor.constraint(
equalTo: safeGuide.leadingAnchor),
button.trailingAnchor.constraint(
equalTo: safeGuide.trailingAnchor),
])
SafeAreaLayoutGuide в UIKit определяет четыре anchor — top, bottom, leading, trailing — которые автоматически учитывают notch, StatusBar и Home Indicator. Этот подход работает на всех устройствах iOS, начиная с iOS 11. В SwiftUI тот же эффект достигается через модификатор контента внутри NavigationStack или VStack — SwiftUI автоматически применяет Safe Area Insets.
// SwiftUI: safeAreaInset и ignoresSafeArea
ZStack {
Color.blue
.ignoresSafeArea()
VStack {
Text("Контент в Safe Area")
.foregroundColor(.white)
Spacer()
}
}
.safeAreaInset(edge: .bottom) {
Text("Полоса внизу экрана")
.padding()
.background(.thinMaterial)
}
В SwiftUI .ignoresSafeArea() позволяет фону растянуться за пределы Safe Area, а .safeAreaInset(edge:) добавляет кастомную панель, которая уменьшает Safe Area с указанной стороны. Это стандартный паттерн для навигационных панелей, тулбаров и рекламных баннеров.
В Android Safe Area реализован через WindowInsets (API 30+) и WindowInsetsCompat (библиотека AndroidX). WindowInsets предоставляет отступы для Status Bar, Navigation Bar, IME (клавиатура) и системных жестов. Начиная с Android 10 (API 29), Google рекомендует использовать WindowInsetsCompat.getInsets() с типом WindowInsetsCompat.Type.systemBars() для получения единого набора отступов под все системные элементы.
// Android: WindowInsets (Kotlin)
class MainActivity : AppCompatActivity() {
override fun onCreate(
savedInstanceState: Bundle?
) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(
findViewById(R.id.main_content)
) { view, insets ->
val systemBars = insets.getInsets(
WindowInsetsCompat.Type.systemBars()
)
view.setPadding(
systemBars.left,
systemBars.top,
systemBars.right,
systemBars.bottom
)
ViewCompat.ON_APPLY_WINDOW_INSETS_LISTENER
}
}
}
В этом примере WindowInsets возвращает отступы для всех системных баров — Status Bar сверху, Navigation Bar снизу. setOnApplyWindowInsetsListener вызывается каждый раз при изменении insets (поворот, вызов клавиатуры). Метод systemBars() объединяет статус бар, навигационный бар и бар кастомизации в один набор, что упрощает код.
Начиная с Android 15, Google требует edge-to-edge отображение для всех приложений, таргетирующих новый API. Это означает, что приложение рисуется под системными барами, а Safe Area применяется через handleWindowInsets или WindowInsetController. По данным Android Developer Blog (2025), 68% приложений уже перешли на edge-to-edge, что улучшает визуальное восприятие на устройствах с большими экранами.
Safe Area, Padding и Insets — связанные, но разные понятия. Safe Area — это область экрана, гарантированно свободная от системных элементов. Padding — внутренний отступ элемента от его границ. Insets — конкретные числовые значения отступов, которые возвращает API Safe Area. По данным Apple Tech Notes (2025), путаница между Safe Area и Padding — причина 40% проблем с адаптивностью в сторах приложений.
| Понятие | Определение | Платформа | Изменяемость |
|---|---|---|---|
| Safe Area | Область без системных элементов | iOS, Android | Динамическая |
| Padding | Внутренний отступ внутри view | Все платформы | Статическая |
| Layout Margins | Отступ от краёв layout | iOS (UIKit) | Статическая/динамическая |
| WindowInsets | Системные отступы Android | Android | Динамическая |
Рассмотрим типовые сценарии: Safe Area в UIKit для горизонтальной ориентации с notch, Safe Area в SwiftUI с кастомной панелью, Safe Area в Android Compose. Пример для iOS UIKit — размещение коллекции внутри Safe Area на iPhone с Dynamic Island. Пример для Jetpack Compose — использование WindowInsets в Material 3.
// Jetpack Compose: отступы от Safe Area
@OptIn(ExperimentalMaterial3Api::class)
fun SafeAreaScreen() {
val systemBars = with(
LocalDensity.current
) {
val insets = WindowInsets
.systemBars
.getAsPaddingValues()
PaddingValues(
top = insets.calculateTopPadding(),
bottom = insets.calculateBottomPadding()
)
}
Scaffold(
contentWindowInsets = WindowInsets(
top = systemBars.computeTopPadding(),
bottom = systemBars.computeBottomPadding()
)
) { innerPadding ->
Column(
modifier = Modifier
.padding(innerPadding)
) {
Text("Контент в Safe Area")
}
}
}
В Jetpack Compose Scaffold автоматически учитывает WindowInsets через параметр contentWindowInsets. InnerPadding передаётся в content и применяется внутренним элементам. Column с модификатором padding(innerPadding) гарантирует, что текст не попадёт под системные бары.
По данным анализа App Store Review от Apple (2025), пять наиболее частых ошибок: игнорирование Safe Area в ландшафтной ориентации, использование жёстко заданных отступов вместо SafeAreaLayoutGuide, неправильная обработка Safe Area в UIScrollView, забытые отступы в модальных презентациях и отсутствие адаптации для Dynamic Island. Жёсткие отступы (hardcoded 20px сверху) — самая распространённая ошибка: на iPhone 14 Pro эти 20px превращаются в 59px, и контент обрезается.
Часто задаваемые вопросы
В SwiftUI Safe Area применяется автоматически к большинству контейнеров. Для чтения отступов используйте EnvironmentValues: @Environment(.safeAreaInsets) var safeAreaInsets. Для кастомных панелей используйте .safeAreaInset(edge:content:). Для фона, который должен растянуться под системные элементы, примените .ignoresSafeArea().
Edge-to-edge — режим отображения, при котором приложение рисуется под системными барами (Status Bar, Navigation Bar), а Safe Area применяется через WindowInsets. Начиная с Android 15, Google требует edge-to-edge для всех приложений с targetSdk 35. Реализуется через WindowInsetsCompat или handleWindowInsets в Jetpack Compose.
Да, WebView также должен учитывать Safe Area. В iOS используйте webView.scrollView.contentInsetAdjustmentBehavior = .always. В Android добавьте android:fitsSystemWindows="true" в XML или programmatic padding через ViewCompat.setOnApplyWindowInsetsListener. CSS-окружение (env(safe-area-inset-top)) работает в Safari, но не в системных WebView Android.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также