Показуємо, що таке 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 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.