เมื่อกำหนดเป้าหมายเป็น SDK 35 ขึ้นไปในอุปกรณ์ที่ใช้ Android 15 ขึ้นไป แอปจะแสดงแบบไร้ขอบ หน้าต่างจะขยายเต็มความกว้างและความสูงของจอแสดงผลโดยวาดอยู่หลังแถบระบบ แถบระบบประกอบด้วยแถบสถานะ แถบคำบรรยาย และแถบนําทาง
แอปจำนวนมากมีแถบแอปด้านบน แถบแอปด้านบนควรขยายไปจนถึงขอบด้านบนของหน้าจอและแสดงอยู่หลังแถบสถานะ คุณเลือกได้ว่าจะให้แถบแอปด้านบนหดให้สูงเท่ากับแถบสถานะเมื่อมีการเลื่อนเนื้อหาหรือไม่
แอปจำนวนมากยังมีแถบด้านล่างของแอปหรือแถบนำทางด้านล่างด้วย แถบเหล่านี้ควรยืดไปถึงขอบด้านล่างของหน้าจอและแสดงอยู่หลังแถบนําทางด้วย ไม่เช่นนั้น แอปควรแสดงเนื้อหาที่เลื่อนอยู่หลังแถบนําทาง
เมื่อใช้เลย์เอาต์แบบเต็มหน้าจอในแอป โปรดคำนึงถึงสิ่งต่อไปนี้
- เปิดใช้การแสดงผลแบบไร้ขอบ
- จัดการภาพซ้อนทับ
- ลองแสดงภาพตัวอย่างหลังแถบระบบ

เปิดใช้การแสดงผลแบบไร้ขอบ
หากแอปกำหนดเป้าหมายเป็น SDK 35 ขึ้นไป ระบบจะเปิดใช้การแสดงผลแบบไร้ขอบโดยอัตโนมัติสำหรับอุปกรณ์ Android 15 ขึ้นไป
หากต้องการเปิดใช้การแสดงผลแบบไร้ขอบใน Android เวอร์ชันก่อนหน้า ให้ทำดังนี้
เพิ่มทรัพยากร Dependency ลงในไฟล์
build.gradle
ของแอปหรือโมดูล โดยเพิ่มลงในไลบรารีandroidx.activity
Kotlin
dependencies { val activity_version =
activity_version
// Java language implementation implementation("androidx.activity:activity:$activity_version") // Kotlin implementation("androidx.activity:activity-ktx:$activity_version") }Groovy
dependencies { def activity_version =
activity_version
// Java language implementation implementation 'androidx.activity:activity:$activity_version' // Kotlin implementation 'androidx.activity:activity-ktx:$activity_version' }นําเข้าฟังก์ชันส่วนขยาย
enableEdgeToEdge
ลงในแอป
เปิดใช้แบบไร้ขอบด้วยตนเองโดยโทร enableEdgeToEdge
ใน onCreate
ของ Activity
ควรเรียกใช้ก่อนวันที่ setContentView
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { enableEdgeToEdge() super.onCreate(savedInstanceState) ... }
Java
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { EdgeToEdge.enable(this); super.onCreate(savedInstanceState); ... }
โดยค่าเริ่มต้น enableEdgeToEdge()
จะทําให้แถบของระบบโปร่งใส ยกเว้นในโหมดการนําทางแบบ 3 ปุ่มที่แถบสถานะจะมีม่านโปร่งแสง ระบบจะปรับสีของไอคอนระบบและหน้าจอพร็อพเพอร์ตี้ตามธีมสว่างหรือมืดของระบบ
ฟังก์ชัน enableEdgeToEdge()
จะประกาศโดยอัตโนมัติว่าควรจัดวางแอปจากขอบถึงขอบและปรับสีของแถบระบบ
หากต้องการเปิดใช้การแสดงผลแบบไร้ขอบในแอปโดยไม่ใช้ฟังก์ชัน enableEdgeToEdge()
โปรดดูหัวข้อตั้งค่าการแสดงผลแบบไร้ขอบด้วยตนเอง
จัดการส่วนที่ซ้อนกันโดยใช้ส่วนตัด
มุมมองบางรายการของแอปอาจวาดอยู่หลังแถบระบบ ดังที่แสดงในรูปภาพ 3
คุณสามารถจัดการส่วนที่ซ้อนทับกันได้โดยตอบสนองต่อส่วนตัด ซึ่งจะระบุส่วนที่ตัดกันของหน้าจอกับ UI ของระบบ เช่น แถบนําทางหรือแถบสถานะ การซ้อนทับอาจหมายถึงการแสดงเหนือเนื้อหา แต่ก็อาจบอกแอปเกี่ยวกับท่าทางสัมผัสของระบบได้ด้วย
ประเภทของส่วนตัดที่ใช้กับการแสดงแอปแบบเต็มหน้าจอมีดังนี้
แถบระบบที่ฝังอยู่: เหมาะสําหรับมุมมองที่ผู้ใช้แตะได้และต้องไม่ถูกแถบระบบบดบัง
แสดงส่วนตัดของรอยบาก: สำหรับบริเวณที่อาจมีรอยบากบนหน้าจอเนื่องจากรูปร่างของอุปกรณ์
ส่วนย่อยของท่าทางสัมผัสของระบบ: สำหรับพื้นที่การนำทางด้วยท่าทางสัมผัสที่ระบบใช้ซึ่งมีความสำคัญเหนือกว่าแอปของคุณ
แถบระบบที่ฝัง
แถบระบบที่ฝังอยู่เป็นประเภทที่ฝังอยู่ซึ่งใช้กันมากที่สุด แถบเหล่านี้แสดงถึงพื้นที่ที่ UI ของระบบแสดงในแนว 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 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 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
โดยนำ or เชิงตรรกะของแถบระบบและประเภทของส่วนตัดของจอแสดงผล
ตั้งค่า 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 ของ Android (com.google.android.material) ที่อิงตามมุมมองจำนวนมากจะจัดการส่วนเกินโดยอัตโนมัติ ซึ่งรวมถึง BottomAppBar
, BottomNavigationView
, NavigationRailView
และ NavigationView
อย่างไรก็ตาม AppBarLayout
จะไม่จัดการส่วนตัดโดยอัตโนมัติ เพิ่ม
android:fitsSystemWindows="true"
เพื่อจัดการส่วนแทรกด้านบน
อ่านวิธีจัดการส่วนเกินด้วย Material Components ใน 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 ขึ้นไป ระบบจะบังคับใช้แบบเต็มหน้าจอ
แถบสถานะของระบบและแถบการนำทางด้วยท่าทางสัมผัสจะโปร่งใส แต่แถบนำทางแบบ 3 ปุ่มจะโปร่งแสง โทรหา enableEdgeToEdge
เพื่อให้ใช้งานร่วมกันได้
อย่างไรก็ตาม ค่าเริ่มต้นของระบบอาจใช้ไม่ได้กับบาง Use Case โปรดดูคำแนะนำด้านการออกแบบแถบระบบ Android และการออกแบบแบบเต็มหน้าจอเพื่อพิจารณาว่าจะใช้แถบระบบแบบโปร่งใสหรือแบบทึบแสง
สร้างแถบระบบแบบโปร่งใส
สร้างแถบสถานะที่โปร่งใสโดยกำหนดเป้าหมายเป็น Android 15 (SDK 35) ขึ้นไป หรือเรียกใช้ enableEdgeToEdge()
ด้วยอาร์กิวเมนต์เริ่มต้นสำหรับเวอร์ชันเก่า
สร้างแถบนำทางด้วยท่าทางสัมผัสแบบโปร่งใสโดยกำหนดเป้าหมายเป็น Android 15 ขึ้นไป หรือเรียกใช้ enableEdgeToEdge()
ด้วยอาร์กิวเมนต์เริ่มต้นสำหรับเวอร์ชันเก่า สำหรับแถบนําทางแบบ 3 ปุ่ม ให้ตั้งค่า Window.setNavigationBarContrastEnforced
เป็น false
ไม่เช่นนั้นระบบจะใช้หน้าจอโปร่งแสง
สร้างแถบระบบแบบโปร่งแสง
วิธีสร้างแถบสถานะแบบโปร่งแสงมีดังนี้
- อัปเดต Dependency ของ
androidx-core
เป็น 1.16.0-beta01 ขึ้นไป - ปิดท้ายเลย์เอาต์ XML ด้วย
androidx.core.view.insets.ProtectionLayout
และกำหนดรหัส - เข้าถึง
ProtectionLayout
โดยใช้โปรแกรมเพื่อตั้งค่าการป้องกัน โดยระบุด้านข้างและGradientProtection
ที่มีค่าอัลฟ่า 80% สำหรับแถบสถานะ
<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>
val red = 52 val green = 168 val blue = 83 findViewById<ProtectionLayout>(R.id.list_protection) .setProtections( listOf( GradientProtection( WindowInsetsCompat.Side.TOP, // Ideally, this is the pane's background color // alpha = 204 for an 80% gradient Color.argb(204, red, green, blue) ) ) )
ตรวจสอบว่า ColorInt
ที่ส่งไปยัง GradientProtection
ตรงกับพื้นหลังของเนื้อหา เช่น เลย์เอาต์รายการแบบละเอียดที่แสดงบนอุปกรณ์แบบพับได้อาจมีGradientProtections
ที่แตกต่างกันสำหรับแผงรายการและแผงรายละเอียด
อย่าสร้างแถบนําทางด้วยท่าทางสัมผัสแบบโปร่งแสง หากต้องการสร้างแถบนําทางแบบ 3 ปุ่มที่โปร่งแสง ให้ทําอย่างใดอย่างหนึ่งต่อไปนี้
- หากมีเลย์เอาต์ที่ตัดขึ้นบรรทัดใหม่ใน
ProtectionView
อยู่แล้ว คุณสามารถส่งColorProtection
หรือGradientProtection
เพิ่มเติมไปยังเมธอดsetProtections
ได้ ก่อนที่จะดำเนินการดังกล่าว โปรดตรวจสอบว่าwindow.isNavigationBarContrastEnforced = false
- มิเช่นนั้น ให้ตั้งค่า
window.isNavigationBarContrastEnforced = true
หากแอปเรียกใช้enableEdgeToEdge, window.isNavigationBarContrastEnforced = true
จะเป็นค่าเริ่มต้น
เคล็ดลับอื่นๆ
ตรวจสอบว่ารายการสุดท้ายในรายการไม่ถูกแถบระบบบดบังใน RecyclerView
หรือ NestedScrollView
โดยจัดการส่วนย่อยและตั้งค่า clipToPadding
เป็น false
วิดีโอต่อไปนี้แสดง RecyclerView
ที่ปิดใช้การแสดงผลแบบเต็มหน้าจอ (ซ้าย) และเปิดใช้ (ขวา)
ดูตัวอย่างโค้ดได้ในส่วนสร้างรายการแบบไดนามิกด้วย RecyclerView
แหล่งข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมเกี่ยวกับการขยายขอบจอได้จากข้อมูลอ้างอิงต่อไปนี้
บล็อก
- เคล็ดลับการจัดการส่วนเกินสำหรับการใช้พื้นที่จากขอบถึงขอบของ Android 15
- WindowInsets — Listener ของเลย์เอาต์
การออกแบบ
เอกสารประกอบอื่นๆ
วิดีโอ