Cutouts ใน Compose

รอยบากบนหน้าจอคือพื้นที่ในอุปกรณ์บางเครื่องที่ยื่นเข้าไปในพื้นผิวของจอแสดงผล ซึ่งช่วยให้ได้รับประสบการณ์การใช้งานแบบเต็มหน้าจอไปพร้อมกับมีพื้นที่สำหรับเซ็นเซอร์ที่สำคัญที่ด้านหน้าของอุปกรณ์

ตัวอย่างการตัดภาพในโหมดภาพบุคคล
รูปที่ 1 ตัวอย่างการตัดภาพในโหมดภาพบุคคล
ตัวอย่างการตัดออกในโหมดแนวนอน
รูปที่ 2 ตัวอย่างการตัดออกในโหมดแนวนอน

Android รองรับรอยบากในการแสดงผลบนอุปกรณ์ที่ใช้ Android 9 (API ระดับ 28) ขึ้นไป อย่างไรก็ตาม ผู้ผลิตอุปกรณ์ยังรองรับส่วนตัดบนจอแสดงผลในอุปกรณ์ที่ใช้ Android 8.1 หรือต่ำกว่าได้ด้วย

หน้านี้จะอธิบายวิธีใช้การรองรับอุปกรณ์ที่มีรอยบากในเครื่องมือเขียน รวมถึงวิธีใช้พื้นที่รอยบาก ซึ่งเป็นสี่เหลี่ยมผืนผ้าแบบเต็มขอบบนพื้นผิวของจอแสดงผลที่มีรอยบาก

เคสเริ่มต้น

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

ตัวอย่างเช่น เมื่อคุณใช้ Modifier.windowInsetsPadding(WindowInsets.safeContent) หรือ Modifier.windowInsetsPadding(WindowInsets.safeDrawing) แอปจะไม่วาดในพื้นที่ที่มีการวางรูปภาพตัดออกโดยอัตโนมัติ ทั้ง WindowInsets.safeContent และ WindowInsets.safeDrawing มีข้อมูลส่วนที่ถูกตัดออกของจอแสดงผลและจะไม่วาดภาพในส่วนที่ถูกตัดออกของอุปกรณ์

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    WindowCompat.setDecorFitsSystemWindows(window, false)

    setContent {
        Box(Modifier.windowInsetsPadding(WindowInsets.safeContent)) {
            // Any composable inside here will avoid drawing behind cutouts
        }
    }
}

หากต้องการปรับแต่งลักษณะการทำงานนี้เพิ่มเติม คุณต้องจัดการข้อมูลส่วนที่ตัดออกด้วยตนเอง

จัดการข้อมูลส่วนที่ตัดออกด้วยตนเอง

คุณจัดการรูปภาพที่ตัดออกได้โดยใช้วิธีใดก็ได้ต่อไปนี้

สําหรับการคอมโพสิท เราขอแนะนําให้ตั้งค่า windowLayoutInDisplayCutoutMode เป็น default ในธีมโดยรวม จากนั้นใช้ประโยชน์จาก WindowInsets.displayCutout เพื่อจัดการส่วนแทรกในคอมโพสิท

Canvas(modifier = Modifier.fillMaxSize().windowInsetsPadding(WindowInsets.displayCutout)) {
    drawRect(Color.Red, style = Stroke(2.dp.toPx()))
}

วิธีนี้ช่วยให้คุณใช้การเว้นวรรค displayCutout ได้ตามความจําเป็น หรือละเว้นได้หากไม่จําเป็น

หรือจะใช้การตั้งค่าเดียวกับที่อธิบายไว้ในเอกสารประกอบเกี่ยวกับภาพตัดของมุมมองก็ได้ โดยตั้งค่าธีมกิจกรรม android:windowLayoutInDisplayCutoutMode เป็นตัวเลือกอื่น หรือตั้งค่าแอตทริบิวต์หน้าต่างโดยใช้ window.attributes.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT อย่างไรก็ตาม ระบบจะใช้โหมดการตัดออกกับทั้งกิจกรรม และไม่สามารถควบคุมแยกตามองค์ประกอบแต่ละรายการได้

หากต้องการคำนึงถึงส่วนเว้าของจอแสดงผลในคอมโพสบางรายการแต่ไม่คำนึงถึงคอมโพสอื่นๆ ให้ใช้ WindowInset.displayCutout API นี้ช่วยให้คุณเข้าถึงข้อมูลภาพตัดเมื่อจำเป็น

แนวทางปฏิบัติแนะนำ

โปรดพิจารณาสิ่งต่อไปนี้เมื่อทำงานกับส่วนตัดของจอแสดงผล

  • โปรดคำนึงถึงตําแหน่งองค์ประกอบที่สําคัญของ UI อย่าให้บริเวณที่ตัดออกบดบังข้อความ การควบคุม หรือข้อมูลสำคัญ
  • อย่าวางหรือขยายองค์ประกอบแบบอินเทอร์แอกทีฟที่ต้องใช้การจดจำการสัมผัสที่ละเอียดในพื้นที่ที่ถูกตัดออก ความไวต่อการสัมผัสอาจลดลงในบริเวณที่มีการตัดออก
  • เมื่อทำตามคำแนะนำแบบเต็มขอบ ข้อมูลส่วนที่ถูกตัดออกจะรวมอยู่ในส่วนย่อย safeDrawing / safeContent
  • ใช้ Modifier.windowInsetsPadding(WindowInsets.safeDrawing) เพื่อกำหนดระยะห่างจากขอบที่เหมาะสมกับเนื้อหาของคุณ หากเป็นไปได้ หลีกเลี่ยงการฮาร์ดโค้ดความสูงของแถบสถานะ เนื่องจากอาจทำให้เนื้อหาทับซ้อนกันหรือถูกตัดออก

ทดสอบวิธีที่เนื้อหาแสดงผลด้วยภาพตัด

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

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