เมื่อกิจกรรมของคุณควบคุมการจัดการส่วนแทรกทั้งหมดแล้ว คุณสามารถใช้ Compose API เพื่อยืนยันว่าเนื้อหาไม่ถูกบดบังและองค์ประกอบที่โต้ตอบได้ไม่ซ้อนทับกับ 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 นอกจากนี้ เลย์เอาต์ทั้งหมดที่ใช้ส่วนแทรกเหล่านี้จะเคลื่อนไหวโดยอัตโนมัติเมื่อค่าส่วนแทรกเปลี่ยนแปลง
การจัดการส่วนแทรกเพื่อปรับเลย์เอาต์ Composable มี 3 วิธีดังนี้
ตัวแก้ไขระยะห่างจากขอบ
Modifier.windowInsetsPadding(windowInsets: WindowInsets) จะใช้ส่วนแทรกของหน้าต่างที่ระบุเป็นระยะห่างจากขอบ ซึ่งทำงานเหมือนกับ Modifier.padding
เช่น Modifier.windowInsetsPadding(WindowInsets.safeDrawing) จะใช้ส่วนแทรกการวาดที่ปลอดภัยเป็นระยะห่างจากขอบทั้ง 4 ด้าน
นอกจากนี้ยังมีเมธอดของยูทิลิตีในตัวหลายรายการสำหรับประเภทส่วนแทรกที่พบบ่อยที่สุด
Modifier.safeDrawingPadding() เป็นวิธีหนึ่งที่เทียบเท่ากับ Modifier.windowInsetsPadding(WindowInsets.safeDrawing) ตารางต่อไปนี้แสดงรายการตัวแก้ไขระยะห่างจากขอบในตัวและประเภท WindowInsets ที่แต่ละตัวแก้ไขใช้
ดูสิ่งที่ส่วนแทรกแต่ละประเภทครอบคลุมได้ที่เกี่ยวกับส่วนแทรกของหน้าต่าง
ตัวปรับแต่งขนาดส่วนแทรก
ตัวแก้ไขต่อไปนี้จะใช้จำนวนส่วนแทรกของหน้าต่างโดยกำหนดขนาดของคอมโพเนนต์ให้เป็นขนาดของส่วนแทรก
ใช้ด้านเริ่มต้นของ windowInsets เป็นความกว้าง (เช่น |
|
ใช้ด้านท้ายของ windowInsets เป็นความกว้าง (เช่น |
|
ใช้ด้านบนของ windowInsets เป็นความสูง (เช่น |
|
|
ใช้ด้านล่างของ windowInsets เป็นความสูง (เช่น |
ตัวแก้ไขเหล่านี้มีประโยชน์อย่างยิ่งสำหรับการปรับขนาด Spacer ที่ใช้พื้นที่ของส่วนแทรก
LazyColumn( Modifier.imePadding() ) { // Other content item { Spacer( Modifier.windowInsetsBottomHeight( WindowInsets.systemBars ) ) } }
การรับชมวิดีโอแบบแทรก
ตัวแก้ไขระยะห่างจากขอบของส่วนแทรก (windowInsetsPadding และตัวช่วยอย่าง safeDrawingPadding) จะใช้ส่วนของส่วนแทรกที่ใช้เป็นระยะห่างจากขอบโดยอัตโนมัติ ขณะที่เจาะลึกเข้าไปในแผนผังองค์ประกอบ ตัวปรับแต่งระยะห่างจากขอบของส่วนแทรกที่ฝังอยู่และตัวปรับแต่งขนาดส่วนแทรกจะทราบว่าตัวปรับแต่งระยะห่างจากขอบของส่วนแทรกด้านนอกได้ใช้ส่วนแทรกบางส่วนไปแล้ว และหลีกเลี่ยงการใช้ส่วนแทรกเดียวกันมากกว่า 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)) }
ในกรณีที่จำเป็นต้องใช้ส่วนแทรกหน้าต่างดิบโดยไม่มีการใช้ ให้ใช้ค่า WindowInsets โดยตรง หรือใช้ WindowInsets.asPaddingValues() เพื่อแสดงผล PaddingValues ของส่วนแทรกที่ไม่ได้รับผลกระทบจากการใช้
อย่างไรก็ตาม เนื่องจากข้อควรระวังต่อไปนี้ เราขอแนะนำให้ใช้ตัวแก้ไขระยะห่างจากขอบของส่วนแทรกหน้าต่างและตัวแก้ไขขนาดของส่วนแทรกหน้าต่างทุกครั้งที่ทำได้
เฟสของส่วนแทรกและ Jetpack Compose
Compose ใช้ API หลักของ AndroidX ที่เกี่ยวข้องเพื่ออัปเดตและทำให้ส่วนแทรกเคลื่อนไหว ซึ่งใช้ API ของแพลตฟอร์มที่เกี่ยวข้องซึ่งจัดการส่วนแทรก เนื่องจากลักษณะการทำงานของแพลตฟอร์มดังกล่าว ส่วนแทรกจึงมีความสัมพันธ์พิเศษกับระยะต่างๆ ของ Jetpack Compose
ค่าของส่วนแทรกจะอัปเดตหลังจากระยะการจัดองค์ประกอบ แต่ก่อนระยะเลย์เอาต์ ซึ่งหมายความว่าการอ่านค่าของส่วนแทรกในองค์ประกอบโดยทั่วไปจะใช้ค่าของส่วนแทรกที่ช้ากว่า 1 เฟรม ตัวปรับแต่งในตัวที่อธิบายไว้ในหน้านี้สร้างขึ้นเพื่อเลื่อนการใช้ค่าของส่วนแทรกจนกว่าจะถึงระยะเลย์เอาต์ ซึ่งช่วยให้มั่นใจได้ว่าระบบจะใช้ค่าส่วนแทรกในเฟรมเดียวกับที่อัปเดต