WindowInsets
คือ API มาตรฐานใน Jetpack Compose สำหรับการจัดการพื้นที่ของหน้าจอที่ UI ของระบบบดบังบางส่วนหรือทั้งหมด
โดย
พื้นที่เหล่านี้รวมถึงแถบสถานะ แถบนำทาง และแป้นพิมพ์บนหน้าจอ หรือจะส่ง WindowInsetsRulers
ที่กำหนดไว้ล่วงหน้า เช่น SafeDrawing
ไปยัง Modifier.fitInside
หรือ Modifier.fitOutside
เพื่อจัดแนวเนื้อหาให้ตรงกับแถบระบบและรอยบากของจอแสดงผล หรือสร้าง WindowInsetsRulers
ที่กำหนดเองก็ได้
ข้อดีของ WindowInsetsRulers
- หลีกเลี่ยงความซับซ้อนในการใช้งาน: ทำงานในระยะการจัดวาง
ของเลย์เอาต์ ซึ่งหมายความว่าการดำเนินการนี้จะข้ามเชนการบริโภคที่แทรกอย่างสมบูรณ์ และจะระบุตำแหน่งที่ถูกต้องและแน่นอนของแถบระบบและรอยบากของจอแสดงผลได้เสมอ ไม่ว่าเลย์เอาต์ระดับบนสุดจะทำอะไรก็ตาม การใช้เมธอด
Modifier.fitInside
หรือModifier.fitOutside
จะช่วยแก้ปัญหา เมื่อ Composable บรรพบุรุษใช้ Insets อย่างไม่ถูกต้อง - หลีกเลี่ยงแถบระบบได้อย่างง่ายดาย: ช่วยให้เนื้อหาแอปหลีกเลี่ยงแถบระบบ
และรอยบากบนจอแสดงผล และอาจตรงไปตรงมากว่าการใช้
WindowInsets
โดยตรง - ปรับแต่งได้สูง: นักพัฒนาแอปสามารถจัดเนื้อหาให้สอดคล้องกับไม้บรรทัดที่กำหนดเอง และควบคุมเลย์เอาต์ได้อย่างแม่นยำด้วยเลย์เอาต์ที่กำหนดเอง
ข้อเสียของ WindowInsetsRulers
- ใช้สําหรับการวัดผลไม่ได้: เนื่องจากทํางานในระหว่างระยะการจัดวาง ข้อมูลตําแหน่งที่ให้จึงไม่พร้อมใช้งานในระหว่าง ระยะการวัดผลก่อนหน้านี้
- อาจทำให้เลย์เอาต์ไม่เสถียร: อาจทำให้เกิดข้อขัดข้องหากขนาดเลย์เอาต์หลัก
ขึ้นอยู่กับขนาดของเลย์เอาต์ย่อย เนื่องจากบุตรหลานที่ใช้
WindowInsetsRulers
อาจเปลี่ยนตำแหน่งหรือขนาดในระหว่างการจัดวาง จึงอาจทำให้เกิดวงจรเลย์เอาต์ที่ไม่เสถียร
สร้าง WindowInsetsRulers
ที่กำหนดเอง
คุณจัดแนวเนื้อหากับไม้บรรทัดที่กำหนดเองได้ ตัวอย่างเช่น พิจารณากรณีการใช้งานที่ Composable หลักจัดการ Inset อย่างไม่ถูกต้อง ซึ่งทำให้เกิดปัญหาการเว้นวรรคใน Composable ย่อยที่อยู่ปลายน้ำ
แม้ว่าปัญหานี้จะแก้ไขได้ด้วยวิธีอื่นๆ รวมถึงการใช้ Modifier.fitInside
แต่คุณก็สร้างไม้บรรทัดที่กำหนดเองเพื่อจัดแนว Composable ขององค์ประกอบย่อยได้อย่างแม่นยำโดยไม่ต้องแก้ไขปัญหาในองค์ประกอบหลักต้นทางได้เช่นกัน ดังตัวอย่างและวิดีโอต่อไปนี้
@Composable fun WindowInsetsRulersDemo(modifier: Modifier) { Box( contentAlignment = BottomCenter, modifier = modifier .fillMaxSize() // The mistake that causes issues downstream, as .padding doesn't consume insets. // While it's correct to instead use .windowInsetsPadding(WindowInsets.navigationBars), // assume it's difficult to identify this issue to see how WindowInsetsRulers can help. .padding(WindowInsets.navigationBars.asPaddingValues()) ) { TextField( value = "Demo IME Insets", onValueChange = {}, modifier = modifier // Use alignToSafeDrawing() instead of .imePadding() to precisely place this child // Composable without having to fix the parent upstream. .alignToSafeDrawing() // .imePadding() // .fillMaxWidth() ) } } fun Modifier.alignToSafeDrawing(): Modifier { return layout { measurable, constraints -> if (constraints.hasBoundedWidth && constraints.hasBoundedHeight) { val placeable = measurable.measure(constraints) val width = placeable.width val height = placeable.height layout(width, height) { val bottom = WindowInsetsRulers.SafeDrawing.current.bottom .current(0f).roundToInt() - height val right = WindowInsetsRulers.SafeDrawing.current.right .current(0f).roundToInt() val left = WindowInsetsRulers.SafeDrawing.current.left .current(0f).roundToInt() measurable.measure(Constraints.fixed(right - left, height)) .place(left, bottom) } } else { val placeable = measurable.measure(constraints) layout(placeable.width, placeable.height) { placeable.place(0, 0) } } } }
วิดีโอต่อไปนี้แสดงตัวอย่างการใช้ IME ที่มีปัญหา
ซึ่งเกิดจากองค์ประกอบหลักต้นทางในรูปภาพทางด้านซ้าย และการใช้ไม้บรรทัดที่กำหนดเอง
เพื่อแก้ไขปัญหาทางด้านขวา โดยจะมีการแสดงระยะห่างเพิ่มเติมใต้ TextField
Composable เนื่องจากองค์ประกอบระดับบนไม่ได้ใช้ระยะห่างของแถบนำทาง โดยวาง
child ในตำแหน่งที่ถูกต้องในรูปภาพด้านขวาโดยใช้ไม้บรรทัดที่กำหนดเอง
ดังที่เห็นในโค้ดตัวอย่างก่อนหน้า
ยืนยันว่าผู้ปกครองถูกจำกัด
หากต้องการใช้ WindowInsetsRulers
อย่างปลอดภัย โปรดตรวจสอบว่าผู้ปกครองได้ระบุข้อจำกัดที่ถูกต้อง
ผู้ปกครองต้องมีขนาดที่กำหนดไว้และไม่สามารถอิงตามขนาดของบุตรหลานที่ใช้ WindowInsetsRulers
ใช้ fillMaxSize
หรือตัวแก้ไขขนาดอื่นๆ
ใน Composable หลัก
ในทำนองเดียวกัน การวาง Composable ที่ใช้ WindowInsetsRulers
ภายใน
คอนเทนเนอร์เลื่อน เช่น verticalScroll
อาจทำให้เกิดลักษณะการทำงานที่ไม่คาดคิด เนื่องจาก
คอนเทนเนอร์เลื่อนมีข้อจำกัดด้านความสูงที่ไม่จำกัด ซึ่ง
ไม่สอดคล้องกับตรรกะของไม้บรรทัด