เมื่อ Activity ควบคุมการจัดการ Inset ทั้งหมดแล้ว คุณจะใช้ API ของ Compose เพื่อยืนยันว่าเนื้อหาไม่ถูกบดบังและองค์ประกอบที่โต้ตอบได้ไม่ ทับซ้อนกับ UI ของระบบ นอกจากนี้ API เหล่านี้ยังซิงค์เลย์เอาต์ของแอปกับการเปลี่ยนแปลงส่วนที่เว้นไว้ด้วย
จัดการระยะขอบโดยใช้ตัวปรับขนาดหรือระยะขอบ
ตัวอย่างเช่น นี่คือวิธีพื้นฐานที่สุดในการใช้ระยะขอบกับเนื้อหา ของทั้งแอป
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { Box(Modifier.safeDrawingPadding()) { // the rest of the app } } }
ข้อมูลโค้ดนี้ใช้ส่วนที่เว้นไว้ของหน้าต่าง safeDrawing เป็นระยะห่างจากขอบรอบๆ
เนื้อหาทั้งหมดของแอป แม้ว่าวิธีนี้จะช่วยให้มั่นใจได้ว่าองค์ประกอบที่โต้ตอบได้จะไม่
ทับซ้อนกับ UI ของระบบ แต่ก็หมายความว่าไม่มีส่วนใดของแอปที่จะวาดอยู่ด้านหลัง
UI ของระบบเพื่อให้ได้เอฟเฟกต์แบบไร้ขอบ หากต้องการใช้ประโยชน์จากทั้งหน้าต่างอย่างเต็มที่ คุณต้องปรับแต่งตำแหน่งที่ใช้ระยะขอบบนหน้าจอทีละหน้าจอ
หรือทีละคอมโพเนนต์
ภาพซ้อนประเภทเหล่านี้ทั้งหมดจะเคลื่อนไหวโดยอัตโนมัติด้วยภาพเคลื่อนไหวของ IME ที่พอร์ตกลับไปยัง API 21 นอกจากนี้ เลย์เอาต์ทั้งหมดที่ใช้ระยะขอบเหล่านี้จะ เคลื่อนไหวโดยอัตโนมัติด้วยเมื่อค่าระยะขอบเปลี่ยนแปลง
การจัดการระยะขอบเพื่อปรับเลย์เอาต์ที่เขียนด้วย Compose ทำได้ 3 วิธีดังนี้
ตัวปรับระยะห่างจากขอบ
Modifier.windowInsetsPadding(windowInsets: WindowInsets) จะใช้
ระยะขอบหน้าต่างที่ระบุเป็นระยะเว้นวรรค ซึ่งจะทำงานเหมือนกับ Modifier.padding
เช่น Modifier.windowInsetsPadding(WindowInsets.safeDrawing) จะใช้
ระยะขอบที่ปลอดภัยเป็นระยะห่างจากขอบทั้ง 4 ด้าน
นอกจากนี้ยังมีเมธอดยูทิลิตีในตัวหลายรายการสำหรับประเภทส่วนที่เว้นไว้ที่พบบ่อยที่สุด
Modifier.safeDrawingPadding() เป็นหนึ่งในวิธีดังกล่าว ซึ่งเทียบเท่ากับ
Modifier.windowInsetsPadding(WindowInsets.safeDrawing) โดยมีตัวปรับแต่งที่คล้ายกัน
สำหรับประเภทส่วนที่เว้นไว้
ตัวปรับแต่งขนาดส่วนที่เว้นไว้
ตัวแก้ไขต่อไปนี้จะใช้จำนวนการแทรกหน้าต่างโดยการตั้งค่าขนาดของ คอมโพเนนต์ให้เป็นขนาดของการแทรก
ใช้ด้านเริ่มต้นของ WindowInsets เป็นความกว้าง (เช่น |
|
ใช้ด้านสิ้นสุดของ WindowInsets เป็นความกว้าง (เช่น |
|
ใช้ด้านบนของ WindowInsets เป็นความสูง (เช่น |
|
|
ใช้ด้านล่างของ WindowInsets เป็นความสูง (เช่น |
ตัวปรับแต่งเหล่านี้มีประโยชน์อย่างยิ่งสำหรับการกำหนดขนาด Spacer ที่ใช้พื้นที่ของระยะขอบ
LazyColumn( Modifier.imePadding() ) { // Other content item { Spacer( Modifier.windowInsetsBottomHeight( WindowInsets.systemBars ) ) } }
การใช้งานฟีเจอร์ภาพซ้อนภาพ
ตัวแก้ไขระยะขอบด้านใน (windowInsetsPadding และตัวช่วยอย่าง
safeDrawingPadding) จะใช้ส่วนของระยะขอบด้านในที่
ใช้เป็นระยะขอบโดยอัตโนมัติ ในขณะที่เจาะลึกเข้าไปในแผนผัง Composition ตัวปรับแต่งระยะห่างจากขอบภายในที่ซ้อนกัน และตัวปรับแต่งขนาดส่วนที่เว้นไว้ภายในจะทราบว่าตัวปรับแต่งระยะห่างจากขอบภายในด้านนอกได้ใช้ส่วนที่เว้นไว้ภายในบางส่วนไปแล้ว และหลีกเลี่ยง การใช้ส่วนที่เว้นไว้ภายในส่วนเดียวกันมากกว่า 1 ครั้ง ซึ่งจะทำให้มีพื้นที่ว่างมากเกินไป
ตัวแก้ไขขนาดส่วนที่เว้นไว้ยังหลีกเลี่ยงการใช้ส่วนที่เว้นไว้ส่วนเดียวกันมากกว่า 1 ครั้ง หากมีการใช้ส่วนที่เว้นไว้ไปแล้ว อย่างไรก็ตาม เนื่องจากมีการเปลี่ยนขนาดโดยตรง จึงไม่ได้ใช้ระยะขอบเอง
ด้วยเหตุนี้ ตัวแก้ไขระยะขอบที่ซ้อนกันจึงเปลี่ยนจำนวน ระยะขอบที่ใช้กับแต่ละ Composable โดยอัตโนมัติ
ดูLazyColumnตัวอย่างเดียวกันกับก่อนหน้านี้ LazyColumnจะได้รับการปรับขนาดโดยตัวแก้ไข imePadding ภายใน LazyColumn รายการสุดท้ายจะมีขนาดเท่ากับความสูงของด้านล่างของแถบระบบ ดังนี้
LazyColumn( Modifier.imePadding() ) { // Other content item { Spacer( Modifier.windowInsetsBottomHeight( WindowInsets.systemBars ) ) } }
เมื่อปิด IME แล้ว imePadding() จะไม่ใช้การเว้นวรรค ดังนั้น
จึงไม่มีการใช้ระยะขอบ และความสูงของ Spacer จะตรงกับแถบระบบด้านล่าง
เมื่อ IME เปิดขึ้น ขอบของ IME จะเคลื่อนไหวให้ตรงกับขนาดของ IME และimePadding()ตัวแก้ไขจะเริ่มใช้ระยะห่างจากด้านล่างเพื่อปรับขนาดLazyColumnเมื่อ IME เปิดขึ้น เมื่อตัวแก้ไข imePadding() เริ่มใช้
ระยะห่างจากด้านล่าง ก็จะเริ่มใช้ระยะห่างจากขอบด้านในจำนวนดังกล่าวด้วย ดังนั้นความสูงของ Spacer จะเริ่มลดลง เนื่องจากตัวแก้ไข imePadding() ได้ใช้การเว้นวรรคสำหรับแถบระบบไปแล้ว เมื่อ
imePadding() ตัวแก้ไขใช้ระยะห่างจากขอบด้านล่างที่มีขนาดใหญ่กว่า
แถบระบบ ความสูงของ Spacer จะเป็น 0
เมื่อ IME ปิดลง การเปลี่ยนแปลงจะเกิดขึ้นในทางกลับกัน โดย Spacer จะขยาย
จากความสูงเป็น 0 เนื่องจาก imePadding() ใช้พื้นที่น้อยกว่าแถบระบบด้านล่าง
สุดท้าย Spacerจะมีความสูงเท่ากับแถบระบบเมื่อ IME เคลื่อนไหวออกจนสุด
TextFieldลักษณะการทำงานนี้เกิดขึ้นจากการสื่อสารระหว่างตัวแก้ไขทั้งหมด
windowInsetsPadding และสามารถปรับเปลี่ยนได้ด้วยวิธีอื่นๆ 2-3 วิธี
Modifier.consumeWindowInsets(insets: WindowInsets) ยังใช้ระยะขอบภายใน
ในลักษณะเดียวกับ Modifier.windowInsetsPadding แต่ไม่ได้ใช้
ระยะขอบภายในที่ใช้เป็นระยะเว้น ซึ่งจะเป็นประโยชน์เมื่อใช้ร่วมกับตัวแก้ไขขนาดส่วนที่เว้นไว้ เพื่อระบุให้องค์ประกอบที่อยู่ระดับเดียวกันทราบว่ามีการใช้ส่วนที่เว้นไว้ไปแล้วจำนวนหนึ่ง
Column(Modifier.verticalScroll(rememberScrollState())) { Spacer(Modifier.windowInsetsTopHeight(WindowInsets.systemBars)) Column( Modifier.consumeWindowInsets( WindowInsets.systemBars.only(WindowInsetsSides.Vertical) ) ) { // content Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime)) } Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.systemBars)) }
Modifier.consumeWindowInsets(paddingValues: PaddingValues) ทำงานคล้ายกับเวอร์ชันที่มีอาร์กิวเมนต์ WindowInsets มาก แต่ใช้ PaddingValues ที่กำหนดเอง ซึ่งมีประโยชน์ในการแจ้งให้บุตรหลานทราบเมื่อมีการเว้นที่ว่างหรือการเว้นระยะห่างโดยกลไกอื่นที่ไม่ใช่ตัวแก้ไขการเว้นที่ว่างภายใน เช่น Modifier.padding หรือตัวเว้นระยะห่างที่มีความสูงคงที่
Column(Modifier.padding(16.dp).consumeWindowInsets(PaddingValues(16.dp))) { // content Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime)) }
ในกรณีที่ต้องการใช้ Window Insets ดิบโดยไม่ต้องใช้ ให้ใช้ค่า WindowInsets โดยตรง หรือใช้ WindowInsets.asPaddingValues() เพื่อ
แสดงผล PaddingValues ของ Insets ที่ไม่ได้รับผลกระทบจากการใช้
อย่างไรก็ตาม เนื่องจากข้อควรระวังต่อไปนี้ เราขอแนะนำให้ใช้ตัวแก้ไขระยะขอบของหน้าต่าง
และตัวแก้ไขขนาดของระยะขอบของหน้าต่างทุกครั้งที่เป็นไปได้
ระยะขอบและเฟสของ Jetpack Compose
Compose ใช้ AndroidX Core API ที่อยู่เบื้องหลังเพื่ออัปเดตและเคลื่อนไหว Inset ซึ่งใช้ Platform API ที่อยู่เบื้องหลังในการจัดการ Inset เนื่องจากลักษณะการทำงานของแพลตฟอร์มดังกล่าว Insets จึงมีความสัมพันธ์พิเศษกับเฟสของ Jetpack Compose
ค่าของ Insets จะได้รับการอัปเดตหลังจากเฟสการจัดองค์ประกอบ แต่ก่อนเฟสเลย์เอาต์ ซึ่งหมายความว่าการอ่านค่าของ Insets ใน Composition โดยทั่วไปจะใช้ค่าของ Insets ที่ช้าไป 1 เฟรม ตัวปรับแต่งในตัวที่อธิบายไว้ในหน้านี้สร้างขึ้นเพื่อชะลอการใช้ค่าของส่วนที่เว้นไว้จนกว่าจะถึงขั้นตอนเลย์เอาต์ ซึ่งจะช่วยให้มั่นใจได้ว่าระบบจะใช้ค่าส่วนที่เว้นไว้ในเฟรมเดียวกันเมื่อมีการอัปเดต