เรานำเสนอว่า 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 — ขนาด notch ที่แตกต่างกัน, Dynamic Island, มุมโค้งมน, ตัวบ่งชี้ Safe Area ทำให้ developers ไม่ต้องกังวลกับความแตกต่างเหล่านี้โดยการจัดหา API ที่เป็นหนึ่งเดียวสำหรับระยะห่างแบบปรับได้ ตามข้อมูลของ Apple Developer (2025) iOS ใช้ Safe Area โดยอัตโนมัติกับ root view แต่ UICollectionView และ UIScrollView ต้องการการกำหนดค่าด้วยตนเอง
| อุปกรณ์ | ประเภทรอยบาก | ระยะห่างด้านบน | ระยะห่างด้านล่าง | StatusBar |
|---|---|---|---|---|
| iPhone SE (รุ่นที่ 3) | ไม่มี | 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 กำหนดจุดยึดสี่จุด — บน, ล่าง, ต้น, ปลาย — ซึ่งพิจารณา 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 ถูกเรียกทุกครั้งที่ระยะห่างเปลี่ยนแปลง (การหมุน, การเรียกแป้นพิมพ์) เมธอด 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 | ระยะห่างจากขอบเลย์เอาต์ | 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 ถูกส่งต่อไปยังเนื้อหาและนำไปใช้กับองค์ประกอบภายใน Column ที่มีตัวปรับแต่ง padding(innerPadding) รับประกันว่าข้อความจะไม่ไปอยู่ใต้แถบระบบ
ตามการวิเคราะห์ App Store Review โดย Apple (2025) ข้อผิดพลาดห้าประการที่พบบ่อยที่สุดคือ: การละเลย Safe Area ในแนวนอน, การใช้ระยะห่างแบบตายตัวแทน SafeAreaLayoutGuide, การจัดการ Safe Area ที่ไม่ถูกต้องใน UIScrollView, การลืมระยะห่างในการนำเสนอแบบ modal และการขาดการปรับตัวสำหรับ Dynamic Island ระยะห่างแบบตายตัว (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 หรือ padding ผ่านโปรแกรมผ่าน ViewCompat.setOnApplyWindowInsetsListener สภาพแวดล้อม CSS (env(safe-area-inset-top)) ทำงานใน Safari แต่ไม่ทำงานใน WebView ของระบบ Android
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ