หากต้องการอนุญาตให้แอปควบคุมตำแหน่งที่จะวาดเนื้อหาได้อย่างเต็มที่ ให้ทำตามขั้นตอนการตั้งค่าต่อไปนี้ หากไม่มีขั้นตอนเหล่านี้ แอปอาจวาดสีดำหรือสีทึบไว้ด้านหลัง UI ของระบบ หรืออาจไม่เคลื่อนไหวพร้อมกับแป้นพิมพ์ซอฟต์แวร์
- กำหนดเป้าหมายเป็น Android 15 (API ระดับ 35) ขึ้นไปเพื่อบังคับใช้การแสดงผลแบบขอบต่อขอบ ใน Android 15 ขึ้นไป แอปของคุณแสดงอยู่ด้านหลัง UI ของระบบ คุณ ปรับ UI ของแอปได้โดยการจัดการ Inset
- หรือจะเรียกใช้
enableEdgeToEdge()
ในActivity.onCreate()
ก็ได้ ซึ่งจะช่วยให้แอปของคุณแสดงแบบไร้ขอบใน Android เวอร์ชันก่อนหน้า ตั้งค่า
android:windowSoftInputMode="adjustResize"
ในรายการAndroidManifest.xml
กิจกรรม การตั้งค่านี้ช่วยให้แอปได้รับขนาด ของ IME ซอฟต์แวร์เป็นระยะขอบ ซึ่งจะช่วยให้คุณใช้เลย์เอาต์ที่เหมาะสม และการเว้นวรรคเมื่อ IME ปรากฏและหายไปในแอป<!-- In your AndroidManifest.xml file: --> <activity android:name=".ui.MainActivity" android:label="@string/app_name" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.MyApplication" android:exported="true">
ใช้ Compose API
เมื่อกิจกรรมของคุณควบคุมการจัดการระยะขอบทั้งหมดแล้ว คุณจะใช้ 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 นอกจากนี้ เลย์เอาต์ทั้งหมดที่ใช้ระยะขอบเหล่านี้จะมีการเคลื่อนไหวโดยอัตโนมัติเมื่อค่าระยะขอบเปลี่ยนแปลง
การใช้ประเภท Inset เหล่านี้เพื่อปรับเลย์เอาต์ที่ประกอบได้มี 2 วิธีหลักๆ ได้แก่ ตัวแก้ไข Padding และตัวแก้ไขขนาด Inset
ตัวแก้ไขระยะห่างจากขอบ
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
) จะใช้ส่วนของระยะขอบด้านในที่
ใช้เป็นระยะขอบโดยอัตโนมัติ ขณะที่เจาะลึกเข้าไปในแผนผังการจัดองค์ประกอบ ตัวแก้ไขระยะขอบภายในแบบซ้อนกันและตัวแก้ไขขนาดระยะขอบภายในจะทราบว่าตัวแก้ไขระยะขอบภายในด้านนอกได้ใช้ระยะขอบภายในบางส่วนไปแล้ว และหลีกเลี่ยงการใช้ระยะขอบภายในส่วนเดียวกันมากกว่า 1 ครั้ง ซึ่งจะทำให้มีพื้นที่ว่างมากเกินไป
ตัวแก้ไขขนาดการแทรกยังหลีกเลี่ยงการใช้ส่วนเดียวกันของการแทรกมากกว่า 1 ครั้ง หากมีการใช้การแทรกไปแล้ว อย่างไรก็ตาม เนื่องจากมีการเปลี่ยนขนาดโดยตรง จึงไม่ได้ใช้ระยะขอบเอง
ด้วยเหตุนี้ ตัวแก้ไขระยะขอบแบบซ้อนจึงเปลี่ยนจำนวน ระยะขอบที่ใช้กับแต่ละ Composable โดยอัตโนมัติ
ดูLazyColumn
ตัวอย่างเดียวกันกับก่อนหน้านี้ LazyColumn
จะได้รับการปรับขนาดโดยตัวแก้ไข imePadding
ภายใน LazyColumn
รายการสุดท้ายจะมีขนาดเท่ากับความสูงของด้านล่างของแถบระบบ ดังนี้
LazyColumn( Modifier.imePadding() ) { // Other content item { Spacer( Modifier.windowInsetsBottomHeight( WindowInsets.systemBars ) ) } }
เมื่อปิด IME ตัวแก้ไข imePadding()
จะไม่ใช้การเว้นวรรค เนื่องจาก
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
แต่ไม่ได้ใช้
ระยะขอบภายในที่ใช้เป็นระยะเว้น ซึ่งจะเป็นประโยชน์เมื่อใช้ร่วมกับตัวแก้ไข inset
size เพื่อระบุให้องค์ประกอบที่อยู่ติดกันทราบว่ามีการใช้ระยะขอบภายในไปแล้ว
จำนวนหนึ่ง
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 ใช้ AndroidX Core API พื้นฐานเพื่ออัปเดตและเคลื่อนไหว Inset ซึ่งใช้ Platform API พื้นฐานที่จัดการ Inset เนื่องจากลักษณะการทำงานของแพลตฟอร์มดังกล่าว Insets จึงมีความสัมพันธ์พิเศษกับเฟสของ Jetpack Compose
ค่าของระยะขอบจะได้รับการอัปเดตหลังจากเฟสการจัดองค์ประกอบ แต่ก่อนเฟสเลย์เอาต์ ซึ่งหมายความว่าการอ่านค่าของ Insets ใน Composition โดยทั่วไปจะใช้ค่าของ Insets ที่ช้าไป 1 เฟรม ตัวแก้ไขในตัว ที่อธิบายไว้ในหน้านี้สร้างขึ้นเพื่อหน่วงเวลาการใช้ค่าของ ระยะขอบจนกว่าจะถึงเฟสเลย์เอาต์ ซึ่งจะช่วยให้มั่นใจได้ว่าระบบจะใช้ค่าระยะขอบใน เฟรมเดียวกันเมื่อมีการอัปเดต