WindowInsets เป็น API มาตรฐานใน Jetpack Compose สำหรับจัดการพื้นที่ของหน้าจอที่ถูกบดบังบางส่วนหรือทั้งหมดโดย UI ของระบบ พื้นที่เหล่านี้รวมถึงแถบสถานะ แถบนำทาง และแป้นพิมพ์บนหน้าจอ หรือจะส่ง WindowInsetsRulers ที่กำหนดไว้ล่วงหน้า เช่น SafeDrawing ไปยัง Modifier.fitInside หรือ Modifier.fitOutside เพื่อจัดแนวเนื้อหาให้สอดคล้องกับแถบระบบและหน้าจอรอยบาก หรือสร้าง WindowInsetsRulers ที่กำหนดเองก็ได้
ข้อดีของ WindowInsetsRulers
- หลีกเลี่ยงความซับซ้อนในการใช้ทรัพยากร: ฟังก์ชันนี้จะทำงานในระยะการวางตำแหน่งของเลย์เอาต์ ซึ่งหมายความว่าระบบจะข้ามเชนการใช้ส่วนแทรกโดยสมบูรณ์ และสามารถระบุตำแหน่งที่ถูกต้องและแน่นอนของแถบระบบและหน้าจอรอยบากได้เสมอ ไม่ว่าเลย์เอาต์หลักจะทำอะไรก็ตาม การใช้เมธอด
Modifier.fitInsideหรือModifier.fitOutsideจะช่วยแก้ปัญหาเมื่อ Composable ระดับบนใช้ส่วนแทรกอย่างไม่ถูกต้อง - หลีกเลี่ยงแถบระบบได้อย่างง่ายดาย: ช่วยให้เนื้อหาแอปหลีกเลี่ยงแถบระบบและหน้าจอรอยบากได้ และอาจตรงไปตรงมากว่าการใช้
WindowInsetsโดยตรง - ปรับแต่งได้สูง: นักพัฒนาแอปสามารถจัดแนวเนื้อหาให้ตรงกับไม้บรรทัดที่กำหนดเอง และควบคุมเลย์เอาต์ได้อย่างแม่นยำด้วยเลย์เอาต์ที่กำหนดเอง
ข้อเสียของ WindowInsetsRulers
- ใช้สำหรับการวัดผลไม่ได้: เนื่องจากทำงานในระยะการวางตำแหน่ง ข้อมูลตำแหน่งที่ให้จึงไม่พร้อมใช้งานในระยะการวัดผลก่อนหน้า
จัดแนวเนื้อหาด้วยเมธอด Modifier
Modifier.fitInside ช่วยให้แอปจัดเนื้อหาให้สอดคล้องกับแถบระบบและหน้าจอรอยบากได้ ซึ่งใช้แทน WindowInsets ได้
Modifier.fitOutside มักจะตรงกันข้ามกับ Modifier.fitInside
เช่น หากต้องการยืนยันว่าเนื้อหาแอปหลีกเลี่ยงแถบระบบและหน้าจอรอยบาก คุณสามารถใช้ fitInside(WindowInsetsRulers.safeDrawing.current)
@Composable fun FitInsideDemo(modifier: Modifier) { Box( modifier = modifier .fillMaxSize() // Or DisplayCutout, Ime, NavigationBars, StatusBar, etc... .fitInside(WindowInsetsRulers.SafeDrawing.current) ) }
ตารางต่อไปนี้แสดงลักษณะของเนื้อหาแอปที่มีไม้บรรทัดที่กำหนดไว้ล่วงหน้าซึ่งมี Modifier.fitInside หรือ Modifier.fitOutside
| ประเภทไม้บรรทัดที่กำหนดไว้ล่วงหน้า | ||
|---|---|---|
![]() |
![]() |
|
![]() |
ไม่มี |
|
![]() |
![]() |
|
![]() |
ไม่มี (ใช้ |
|
![]() |
![]() |
การใช้ Modifier.fitInside และ Modifier.fitOutside กำหนดให้ Composable ต้องถูกจำกัด ซึ่งหมายความว่าคุณต้องกำหนดตัวแก้ไข เช่น Modifier.size หรือ Modifier.fillMaxSize
ไม้บรรทัดบางอัน เช่น Modifier.fitOutside ใน SafeDrawing และ SystemBars จะแสดงผลไม้บรรทัดหลายอัน ในกรณีนี้ Android จะวาง Composable โดยใช้ไม้บรรทัด 1 อันจากซ้าย บน ขวา ล่าง
หลีกเลี่ยง IME ด้วย Modifier.fitInside
หากต้องการจัดการองค์ประกอบด้านล่างด้วย IME ที่มี Modifier.fitInside ให้ส่ง RectRuler ที่ใช้ค่าด้านในสุดของ NavigationBar และ Ime
@Composable fun FitInsideWithImeDemo(modifier: Modifier) { Box( modifier = modifier .fillMaxSize() .fitInside( RectRulers.innermostOf( WindowInsetsRulers.NavigationBars.current, WindowInsetsRulers.Ime.current ) ) ) { TextField( value = "Demo IME Insets", onValueChange = {}, modifier = modifier.align(Alignment.BottomStart).fillMaxWidth() ) } }
หลีกเลี่ยงแถบสถานะและแถบคำบรรยายด้วย Modifier.fitInside
ในทำนองเดียวกัน หากต้องการยืนยันว่าองค์ประกอบด้านบนหลีกเลี่ยงแถบสถานะและแถบคำอธิบายภาพร่วมกับ Modifier.fitInside ให้ส่ง RectRuler ที่ใช้ค่าด้านในสุดของ StatusBars และ CaptionBar
@Composable fun FitInsideWithStatusAndCaptionBarDemo(modifier: Modifier) { Box( modifier = modifier .fillMaxSize() .fitInside( RectRulers.innermostOf( WindowInsetsRulers.StatusBars.current, WindowInsetsRulers.CaptionBar.current ) ) ) }
สร้าง WindowInsetsRulers ที่กำหนดเอง
คุณจัดแนวเนื้อหาให้ตรงกับไม้บรรทัดที่กำหนดเองได้ ตัวอย่างเช่น ลองพิจารณากรณีการใช้งานที่ Composable หลักจัดการส่วนแทรกอย่างไม่เหมาะสม ซึ่งทำให้เกิดปัญหาเกี่ยวกับระยะห่างจากขอบในองค์ประกอบย่อยที่อยู่ปลายทาง แม้ว่าปัญหานี้จะแก้ไขได้ด้วยวิธีอื่นๆ รวมถึงการใช้ Modifier.fitInside คุณยังสามารถสร้างไม้บรรทัดที่กำหนดเองเพื่อจัดแนวคอมโพสิเบิลย่อยได้อย่างแม่นยำโดยไม่ต้องแก้ไขปัญหาในคอมโพสิเบิลหลักที่อยู่ต้นทาง ดังที่แสดงในตัวอย่างและวิดีโอต่อไปนี้
@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 เนื่องจากองค์ประกอบหลักไม่ได้ใช้ระยะห่างจากขอบของแถบนำทาง ระบบจะวางองค์ประกอบย่อยในตำแหน่งที่ถูกต้องในรูปภาพด้านขวาโดยใช้ไม้บรรทัดที่กำหนดเองดังที่เห็นในตัวอย่างโค้ดก่อนหน้า
ยืนยันว่ามีการจำกัดระดับบน
เพื่อให้ใช้ WindowInsetsRulers ได้อย่างปลอดภัย โปรดตรวจสอบว่าผู้ปกครองระบุข้อจำกัดที่ถูกต้อง องค์ประกอบหลักต้องมีขนาดที่กำหนดไว้และไม่สามารถขึ้นอยู่กับขนาดขององค์ประกอบย่อยที่ใช้ WindowInsetsRulers ใช้ fillMaxSize หรือตัวปรับแต่งขนาดอื่นๆ กับ Composable ระดับบนสุด
ในทำนองเดียวกัน การวาง Composable ที่ใช้ WindowInsetsRulers ไว้ในคอนเทนเนอร์แบบเลื่อนได้ เช่น verticalScroll อาจทำให้เกิดลักษณะการทำงานที่ไม่คาดคิด เนื่องจากคอนเทนเนอร์แบบเลื่อนได้มีข้อจำกัดด้านความสูงที่ไม่มีขอบเขต ซึ่งไม่เข้ากันกับตรรกะของไม้บรรทัด







