نشان میدهیم 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، تعداد انواع صفحهها به ۲۰+ افزایش یافت — اندازههای مختلف بریدگیها، Dynamic Island، گردیها، نشانگرها. Safe Area توسعهدهنده را از این تفاوتها انتزاع میکند و یک API واحد برای فاصلههای تطبیقی فراهم میکند. طبق Apple Developer (2025)، iOS به طور خودکار Safe Area را برای نمای ریشه اعمال میکند، اما برای 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 یک راهنمای طرح است که به هر 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 برای همه برنامههایی که API جدید را هدف قرار میدهند edge-to-edge را الزامی میکند. این بدان معناست که برنامه زیر نوارهای سیستم کشیده میشود و Safe Area از طریق handleWindowInsets یا WindowInsetController اعمال میشود. طبق Android Developer Blog (2025)، ۶۸٪ برنامهها قبلاً به edge-to-edge مهاجرت کردهاند که درک بصری را در دستگاههای با صفحه بزرگ بهبود میبخشد.
Safe Area، Padding و Insets — مفاهیم مرتبط اما متفاوت. Safe Area ناحیهای از صفحه است که تضمیناً از عناصر سیستم عاری است. Padding فاصله داخلی یک عنصر از مرزهای آن است. Insets مقادیر عددی خاص فاصلههایی هستند که توسط API Safe Area بازگردانده میشوند. طبق Apple Tech Notes (2025)، اشتباه گرفتن Safe Area و Padding عامل ۴۰٪ مشکلات تطبیقپذیری در فروشگاههای برنامه است.
| مفهوم | تعریف | پلتفرم | تغییرپذیری |
|---|---|---|---|
| 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 برای همه برنامههای با targetSdk 35 edge-to-edge را الزامی میکند. از طریق WindowInsetsCompat یا handleWindowInsets در Jetpack Compose پیادهسازی میشود.
بله، WebView نیز باید Safe Area را در نظر بگیرد. در iOS از webView.scrollView.contentInsetAdjustmentBehavior = .always استفاده کنید. در Android android:fitsSystemWindows="true" را در XML اضافه کنید یا padding برنامهنویسی از طریق ViewCompat.setOnApplyWindowInsetsListener. محیط CSS (env(safe-area-inset-top)) در Safari کار میکند، اما در WebViewهای سیستمی Android کار نمیکند.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید