เมื่อกำหนดเป้าหมายเป็น SDK 35 ขึ้นไปในอุปกรณ์ที่ใช้ Android 15 ขึ้นไป แอปจะแสดงแบบไร้ขอบ หน้าต่างจะครอบคลุมความกว้างและความสูงทั้งหมดของจอแสดงผลโดยวาดไว้ด้านหลังแถบระบบ แถบระบบประกอบด้วยแถบสถานะ แถบคำบรรยาย และแถบนำทาง
แอปจำนวนมากมีแถบแอปด้านบน แถบแอปด้านบนควรยืดไปจนถึงขอบด้านบนของหน้าจอและแสดงไว้ด้านหลังแถบสถานะ หรือจะให้แถบแอปด้านบนหดลงมาเท่าความสูงของแถบสถานะเมื่อเนื้อหาเลื่อนก็ได้
แอปจำนวนมากยังมีแถบแอปด้านล่างหรือแถบนำทางด้านล่าง แถบเหล่านี้ควรยืดไปจนถึงขอบด้านล่างของหน้าจอและแสดงไว้ด้านหลังแถบนำทางด้วย มิเช่นนั้น แอปควรแสดงเนื้อหาที่เลื่อนได้ไว้ด้านหลังแถบนำทาง
เมื่อใช้เลย์เอาต์แบบไร้ขอบในแอป โปรดคำนึงถึงสิ่งต่อไปนี้
- เปิดใช้การแสดงผลแบบไร้ขอบ
- ใช้เลย์เอาต์แบบปรับได้เพื่อเพิ่มประสิทธิภาพประสบการณ์ของผู้ใช้ ในอุปกรณ์รูปแบบต่างๆ
- จัดการการซ้อนทับของภาพ
- พิจารณาแสดงเลเยอร์โปร่งแสงไว้ด้านหลังแถบระบบ
เปิดใช้การแสดงผลแบบไร้ขอบ
หากแอปกำหนดเป้าหมายเป็น SDK 35 ขึ้นไป ระบบจะเปิดใช้การแสดงผลแบบไร้ขอบโดยอัตโนมัติสำหรับอุปกรณ์ Android 15 ขึ้นไป
หากต้องการเปิดใช้การแสดงผลแบบไร้ขอบใน Android เวอร์ชันก่อนหน้า ให้เรียกใช้
enableEdgeToEdge ใน onCreate ของคุณ Activity
Kotlin
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.enableEdgeToEdge(window)
...
}
Java
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WindowCompat.enableEdgeToEdge(getWindow());
...
}
โดยค่าเริ่มต้น enableEdgeToEdge() จะทำให้แถบระบบโปร่งใส ยกเว้นในโหมดการไปยังส่วนต่างๆ แบบ 3 ปุ่มที่แถบนำทางจะมีเลเยอร์โปร่งแสง ระบบจะปรับสีของไอคอนระบบและเลเยอร์โปร่งแสงตามธีมสว่างหรือธีมมืดของระบบ
หากต้องการเปิดใช้การแสดงผลแบบไร้ขอบในแอปโดยไม่ใช้
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 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 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; });
คอมโพเนนต์เนื้อหา
คอมโพเนนต์เนื้อหา
ของ 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สำหรับแถบสถานะ
<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>
findViewById<ProtectionLayout>(R.id.list_protection) .setProtections( listOf( GradientProtection( WindowInsetsCompat.Side.TOP, // Ideally, this is the pane's background color paneBackgroundColor ) ) )
ตรวจสอบว่า ColorInt ที่ส่งไปยัง GradientProtection ตรงกับพื้นหลังของเนื้อหา ตัวอย่างเช่น เลย์เอาต์รายละเอียดรายการที่แสดงบนอุปกรณ์พับได้อาจมี GradientProtections ที่มีสีแตกต่างกันสำหรับแผงรายการและแผงรายละเอียด
อย่าสร้างแถบนำทางการไปยังส่วนต่างๆ ด้วยท่าทางสัมผัสแบบโปร่งแสง หากต้องการสร้างแถบนำทางแบบ 3 ปุ่มแบบโปร่งแสง ให้ทำอย่างใดอย่างหนึ่งต่อไปนี้
- หากคุณใส่เลย์เอาต์ไว้ใน
ProtectionViewแล้ว คุณสามารถส่งColorProtectionหรือGradientProtectionเพิ่มเติมไปยังเมธอดsetProtectionsได้ ก่อนดำเนินการ ให้ตรวจสอบว่าwindow.isNavigationBarContrastEnforced = false - มิเช่นนั้น ให้ตั้งค่า
window.isNavigationBarContrastEnforced = true
เคล็ดลับอื่นๆ
เคล็ดลับเพิ่มเติมเมื่อจัดการระยะขอบ
ทำให้เนื้อหาที่เลื่อนได้แสดงแบบไร้ขอบ
ตรวจสอบว่ารายการสุดท้ายไม่ได้ถูกแถบระบบบดบังใน RecyclerView หรือ NestedScrollView โดยจัดการระยะขอบและตั้งค่า clipToPadding เป็น false
วิดีโอต่อไปนี้แสดง RecyclerView ที่ปิดใช้ (ซ้าย) และเปิดใช้ (ขวา) การแสดงผลแบบไร้ขอบ
ดูตัวอย่างโค้ดได้ในส่วน สร้างรายการแบบไดนามิกด้วย RecyclerView
ทำให้กล่องโต้ตอบแบบเต็มหน้าจอแสดงแบบไร้ขอบ
หากต้องการทำให้กล่องโต้ตอบแบบเต็มหน้าจอแสดงแบบไร้ขอบ ให้เรียกใช้ enableEdgeToEdge ในกล่องโต้ตอบ
Kotlin
class MyAlertDialogFragment : DialogFragment() {
override fun onStart(){
super.onStart()
dialog?.window?.let { WindowCompat.enableEdgeToEdge(it) }
}
...
}
Java
public class MyAlertDialogFragment extends DialogFragment {
@Override
public void onStart() {
super.onStart();
Dialog dialog = getDialog();
if (dialog != null) {
Window window = dialog.getWindow();
if (window != null) {
WindowCompat.enableEdgeToEdge(window);
}
}
}
...
}
แหล่งข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้การแสดงผลแบบไร้ขอบได้จากข้อมูลอ้างอิงต่อไปนี้
บล็อก
- เคล็ดลับการจัดการระยะขอบสำหรับการบังคับใช้การแสดงผลแบบไร้ขอบของ Android 15
- WindowInsets - Listener สำหรับเลย์เอาต์
การออกแบบ
เอกสารอื่นๆ
วิดีโอ