แสดงเนื้อหาแบบไร้ขอบในแอป

ลองใช้วิธีเขียน
Jetpack Compose เป็นชุดเครื่องมือ UI ที่แนะนำสำหรับ Android ดูวิธีทำงานแบบเต็มหน้าจอในเครื่องมือเขียน

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

แอปจำนวนมากมีแถบแอปด้านบน แถบแอปด้านบนควรขยายไปจนถึงขอบด้านบนของหน้าจอและแสดงอยู่หลังแถบสถานะ คุณเลือกได้ว่าจะให้แถบแอปด้านบนหดให้สูงเท่ากับแถบสถานะเมื่อมีการเลื่อนเนื้อหาหรือไม่

แอปจำนวนมากยังมีแถบด้านล่างของแอปหรือแถบนำทางด้านล่างด้วย แถบเหล่านี้ควรยืดไปถึงขอบด้านล่างของหน้าจอและแสดงอยู่หลังแถบนําทางด้วย ไม่เช่นนั้น แอปควรแสดงเนื้อหาที่เลื่อนอยู่หลังแถบนําทาง

รูปที่ 1 แถบระบบในเลย์เอาต์แบบเต็มหน้าจอ

เมื่อใช้เลย์เอาต์แบบเต็มหน้าจอในแอป โปรดคำนึงถึงสิ่งต่อไปนี้

  1. เปิดใช้การแสดงผลแบบไร้ขอบ
  2. จัดการภาพซ้อนทับ
  3. ลองแสดงภาพตัวอย่างหลังแถบระบบ
ตัวอย่างภาพที่อยู่หลังแถบสถานะ
รูปที่ 2 ตัวอย่างภาพที่อยู่เบื้องหลังแถบสถานะ

เปิดใช้การแสดงผลแบบไร้ขอบ

หากแอปกำหนดเป้าหมายเป็น SDK 35 ขึ้นไป ระบบจะเปิดใช้การแสดงผลแบบไร้ขอบโดยอัตโนมัติสำหรับอุปกรณ์ Android 15 ขึ้นไป

หากต้องการเปิดใช้การแสดงผลแบบไร้ขอบใน Android เวอร์ชันก่อนหน้า ให้ทำดังนี้

  1. เพิ่ม Dependency ลงในไฟล์ build.gradle ของแอปหรือโมดูล โดยเพิ่มบรรทัดต่อไปนี้ในไฟล์ build.gradleandroidx.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'
    }
  2. นําเข้าฟังก์ชันส่วนขยาย 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 ถูกบดบังบางส่วนโดยแถบนําทาง

ตัวอย่างการใช้งานแบบเต็มหน้าจอ แต่แถบนําทางบดบัง FAB
รูปที่ 3 แถบนำทางที่ทับซ้อนกับ FAB ในเลย์เอาต์แบบเต็มหน้าจอ

หากต้องการหลีกเลี่ยงการซ้อนทับภาพประเภทนี้ในโหมดท่าทางสัมผัสหรือโหมดปุ่ม คุณสามารถเพิ่มระยะขอบของมุมมองได้โดยใช้ 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

แถบนำทางแบบโปร่งแสงที่ไม่บัง FAB
รูปที่ 4 การแก้ไขการซ้อนทับของภาพในโหมดปุ่ม

เช่นเดียวกับโหมดการไปยังส่วนต่างๆ ด้วยท่าทางสัมผัส ดังที่แสดงในรูปที่ 5

แบบไร้ขอบพร้อมการไปยังส่วนต่างๆ ด้วยท่าทางสัมผัส
รูปที่ 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

ตัวอย่างส่วนแทรกของท่าทางสัมผัสของระบบ
รูปที่ 6 ส่วนที่ยื่นออกมาของท่าทางสัมผัสของระบบ

คุณสามารถหลีกเลี่ยงการซ้อนกันของส่วนแทรกท่าทางสัมผัสของระบบได้เช่นเดียวกับส่วนแทรกของแถบระบบ โดยการใช้ getInsets(int) กับ WindowInsetsCompat.Type.systemGestures()

ใช้ส่วนตัดเหล่านี้เพื่อย้ายหรือเพิ่มพื้นที่ว่างให้กับมุมมองที่ปัดได้ให้ห่างจากขอบ กรณีการใช้งานที่พบบ่อย ได้แก่ ชีตด้านล่าง การปัดในเกม และภาพสไลด์ที่ใช้ ViewPager2

ใน Android 10 ขึ้นไป ส่วนที่เว้นไว้สำหรับท่าทางสัมผัสของระบบจะมีส่วนที่เว้นไว้ที่ด้านล่างสำหรับท่าทางสัมผัสที่เปิดหน้าจอหลัก และส่วนที่เว้นไว้ที่ด้านซ้ายและขวาสำหรับท่าทางสัมผัสที่กลับ

ตัวอย่างการวัดค่าระยะขอบของท่าทางสัมผัสของระบบ
รูปที่ 7 การวัดค่าระยะห่างจากขอบของท่าทางสัมผัสของระบบ

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีใช้ส่วนตัดของท่าทางสัมผัสของระบบ

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){:.external} จำนวนมากที่อิงตามมุมมองจะจัดการส่วนเกินโดยอัตโนมัติ ซึ่งรวมถึง BottomAppBar, BottomNavigationView, NavigationRailView และ NavigationView

อย่างไรก็ตาม AppBarLayout จะไม่จัดการส่วนตัดโดยอัตโนมัติ เพิ่ม android:fitsSystemWindows="true" เพื่อจัดการส่วนแทรกด้านบน

อ่านวิธีจัดการส่วนเกินด้วย Material Components ใน Compose

โหมดใหญ่พิเศษ

เนื้อหาบางอย่างจะดูได้ดีที่สุดเมื่อเปิดแบบเต็มหน้าจอ ซึ่งจะช่วยให้ผู้ใช้ได้รับประสบการณ์ที่สมจริงยิ่งขึ้น คุณซ่อนแถบระบบและโหมดสมจริงได้โดยใช้คลัง 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());

ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ฟีเจอร์นี้ได้ที่หัวข้อซ่อนแถบระบบสำหรับโหมดสมจริง

การปกป้องแถบระบบ

เมื่อแอปกำหนดเป้าหมายเป็น SDK 35 ขึ้นไป ระบบจะบังคับใช้การแสดงผลแบบไร้ขอบ แถบสถานะของระบบและแถบการนำทางด้วยท่าทางสัมผัสจะโปร่งใส แต่แถบนำทางแบบ 3 ปุ่มจะโปร่งแสง

หากต้องการนำการป้องกันพื้นหลังการนำทางแบบ 3 ปุ่มที่โปร่งแสงเริ่มต้นออก ให้ตั้งค่า Window.setNavigationBarContrastEnforced เป็น false

แหล่งข้อมูลเพิ่มเติม

ดูข้อมูลเพิ่มเติมเกี่ยวกับ WindowInsets, การนำทางด้วยท่าทางสัมผัส และวิธีการทำงานของส่วนแทรกได้ที่แหล่งข้อมูลต่อไปนี้