WindowInsets คือ API มาตรฐานใน Jetpack Compose สำหรับจัดการพื้นที่ของหน้าจอที่ UI ของระบบบดบังบางส่วนหรือทั้งหมด พื้นที่เหล่านี้รวมถึงแถบสถานะ แถบนำทาง และแป้นพิมพ์บนหน้าจอ หรือคุณจะส่ง
WindowInsetsRulersที่กำหนดไว้ล่วงหน้า เช่น
SafeDrawingไปยังModifier.fitInsideหรือModifier.fitOutside
เพื่อจัดแนวเนื้อหาให้ตรงกับแถบระบบและหน้าจอรอยบาก หรือสร้าง
WindowInsetsRulersที่กำหนดเองก็ได้
ข้อดีของ WindowInsetsRulers
- หลีกเลี่ยงความซับซ้อนในการใช้งาน: ทำงานในระยะการจัดวาง
ของเลย์เอาต์ ซึ่งหมายความว่าจะข้ามห่วงโซ่การใช้งานส่วนที่เว้นไว้ทั้งหมด และสามารถระบุตำแหน่งสัมบูรณ์ที่ถูกต้องของแถบระบบและหน้าจอรอยบากได้เสมอ ไม่ว่าเลย์เอาต์หลักจะทำอะไรก็ตาม การใช้เมธอด
Modifier.fitInsideหรือModifier.fitOutsideจะช่วยแก้ปัญหาเมื่อ Composables ระดับบนใช้งานระยะขอบอย่างไม่ถูกต้อง - หลีกเลี่ยงแถบระบบได้อย่างง่ายดาย: ช่วยให้เนื้อหาแอปหลีกเลี่ยงแถบระบบ
และหน้าจอรอยบาก และอาจตรงไปตรงมากว่าการใช้
WindowInsetsโดยตรง - ปรับแต่งได้สูง: นักพัฒนาแอปสามารถจัดแนวเนื้อหาให้ตรงกับไม้บรรทัดที่กำหนดเอง และ ควบคุมเลย์เอาต์ได้อย่างแม่นยำด้วยเลย์เอาต์ที่กำหนดเอง
ข้อเสียของ WindowInsetsRulers
- ใช้สำหรับการวัดไม่ได้: เนื่องจากทำงานในระยะการจัดวาง ข้อมูลตำแหน่งที่ระบุจึงไม่พร้อมใช้งาน ในระยะการวัดก่อนหน้านี้
จัดแนวเนื้อหาด้วยเมธอดตัวปรับแต่ง
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 กำหนดให้ต้องมีการจำกัด Composables ซึ่งหมายความว่าคุณต้องกำหนดตัวปรับแต่ง เช่น Modifier.size หรือ Modifier.fillMaxSize
ไม้บรรทัดบางรายการ เช่น Modifier.fitOutside ใน SafeDrawing และ SystemBars จะแสดงผลไม้บรรทัดหลายรายการ ในกรณีนี้ Android จะวาง Composable โดยใช้ไม้บรรทัดรายการใดรายการหนึ่งจากซ้าย บน ขวา ล่าง
หลีกเลี่ยง 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 ที่กำหนดเอง
คุณสามารถจัดแนวเนื้อหาให้ตรงกับไม้บรรทัดที่กำหนดเองได้ ตัวอย่างเช่น พิจารณากรณีการใช้งานที่ Composables ระดับบนจัดการระยะขอบอย่างไม่เหมาะสม ซึ่งทำให้เกิดปัญหาการเพิ่มระยะห่างใน Composables ระดับล่าง แม้ว่าคุณจะแก้ปัญหานี้ได้ด้วยวิธีอื่นๆ รวมถึงการใช้ Modifier.fitInside แต่คุณยังสร้างไม้บรรทัดที่กำหนดเองเพื่อจัดแนว Composables ระดับล่างได้อย่างแม่นยำโดยไม่ต้องแก้ไขปัญหาใน Composables ระดับบนตามที่แสดงในตัวอย่างและวิดีโอต่อไปนี้
@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 ที่มีปัญหาซึ่งเกิดจาก Composables ระดับบนทางด้านซ้าย และการใช้ไม้บรรทัดที่กำหนดเองเพื่อแก้ไขปัญหาทางด้านขวา ระบบจะแสดงการเพิ่มระยะห่างพิเศษใต้ Composables TextField เนื่องจาก Composables ระดับบนไม่ได้ใช้งานระยะห่างของแถบนำทาง รูปภาพทางด้านขวาแสดง Composables ระดับล่างที่วางอยู่ในตำแหน่งที่ถูกต้องโดยใช้ไม้บรรทัดที่กำหนดเองตามที่แสดงในตัวอย่างโค้ดก่อนหน้า
ตรวจสอบว่ามีการจำกัด Composables ระดับบน
หากต้องการใช้ WindowInsetsRulers อย่างปลอดภัย ให้ตรวจสอบว่า Composables ระดับบนมีการจำกัดที่ถูกต้อง Composables ระดับบนต้องมีขนาดที่กำหนดไว้และไม่ขึ้นอยู่กับขนาดของ Composables ระดับล่างที่ใช้ WindowInsetsRulers ใช้ fillMaxSize หรือตัวปรับแต่งขนาดอื่นๆ ใน Composables ระดับบน
ในทำนองเดียวกัน การวาง Composables ที่ใช้ WindowInsetsRulers ไว้ในคอนเทนเนอร์แบบเลื่อนได้ เช่น verticalScroll อาจทำให้เกิดลักษณะการทำงานที่ไม่คาดคิด เนื่องจากคอนเทนเนอร์แบบเลื่อนได้มีการจำกัดความสูงแบบไม่จำกัด ซึ่งไม่เข้ากันกับตรรกะของไม้บรรทัด







