หากต้องการให้แอปควบคุมตําแหน่งที่จะวาดเนื้อหาได้อย่างเต็มที่ ให้ทําตามการตั้งค่าขั้นตอนเหล่านี้ หากไม่ทำตามขั้นตอนเหล่านี้ แอปอาจวาดสีดำหรือสีพื้นหลัง UI ของระบบ หรือภาพเคลื่อนไหวไม่ซิงค์กับแป้นพิมพ์ซอฟต์แวร์
- กําหนดเป้าหมายเป็น Android 15 (API ระดับ 35) ขึ้นไปเพื่อบังคับใช้การแสดงผลแบบเต็มหน้าจอใน Android 15 ขึ้นไป แอปจะแสดงอยู่หลัง UI ของระบบ คุณสามารถปรับ UI ของแอปได้โดยจัดการส่วนตัด
- (ไม่บังคับ) เรียกใช้
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 นอกจากนี้ เลย์เอาต์ทั้งหมดที่ใช้ส่วนแทรกเหล่านี้จะเคลื่อนไหวโดยอัตโนมัติเมื่อค่าส่วนแทรกเปลี่ยนแปลง
การใช้ประเภทการฝังเหล่านี้เพื่อปรับเลย์เอาต์ Composable มี 2 วิธีหลัก ได้แก่ ตัวแก้ไขระยะห่างจากขอบและตัวแก้ไขขนาดการฝัง
ตัวปรับระยะห่างจากขอบ
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 ครั้งด้วยหากมีการใช้ส่วนตัดไปแล้ว อย่างไรก็ตาม เนื่องจากชิ้นงานเหล่านี้จะเปลี่ยนขนาดโดยตรง จึงไม่ได้กินพื้นที่ส่วนเกินเอง
ด้วยเหตุนี้ ตัวแก้ไขการเว้นวรรคที่ฝังไว้จึงเปลี่ยนจำนวนการเว้นวรรคที่ใช้กับคอมโพสิเบิลแต่ละรายการโดยอัตโนมัติ
เมื่อดูตัวอย่าง 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 วิธี
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 เฟรม ตัวปรับเปลี่ยนในตัวที่อธิบายไว้ในหน้านี้สร้างขึ้นเพื่อเลื่อนเวลาการใช้ค่าของส่วนตัดจนกว่าจะถึงระยะการวางเลย์เอาต์ ซึ่งช่วยให้มั่นใจได้ว่าระบบจะใช้ค่าของส่วนตัดในเฟรมเดียวกันกับที่อัปเดต