แพลตฟอร์ม Android มีหน้าที่วาด UI ของระบบ เช่น แถบสถานะและแถบนําทาง UI ระบบนี้จะแสดงขึ้นไม่ว่าผู้ใช้จะใช้แอปใดก็ตาม
WindowInsets
ให้ข้อมูลเกี่ยวกับ UI ของระบบเพื่อให้มั่นใจว่าแอปจะวาดในพื้นที่ที่ถูกต้องและ UI ของคุณจะไม่ถูกบดบังโดย UI ของระบบ
ใน Android 14 (API ระดับ 34) และต่ำกว่า UI ของแอปจะไม่วาดใต้แถบระบบและส่วนที่ถูกตัดออกของจอแสดงผลโดยค่าเริ่มต้น
ใน Android 15 (API ระดับ 35) ขึ้นไป แอปจะวาดใต้แถบระบบและแสดงส่วนที่ถูกตัดออกเมื่อแอปกำหนดเป้าหมายเป็น SDK 35 ซึ่งส่งผลให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ราบรื่นยิ่งขึ้น และแอปของคุณก็ใช้ประโยชน์จากพื้นที่ในหน้าต่างได้อย่างเต็มที่
การแสดงเนื้อหาที่อยู่หลัง UI ของระบบเรียกว่าการแสดงผลแบบเต็มหน้าจอ ในหน้านี้ คุณจะได้เรียนรู้เกี่ยวกับส่วนตัดต่างๆ วิธีแสดงผลแบบเต็มหน้าจอ และวิธีใช้ API ส่วนตัดเพื่อแสดงภาพ UI แบบเคลื่อนไหวและตรวจสอบว่าเนื้อหาของแอปไม่ถูกบดบังโดยองค์ประกอบ UI ของระบบ
ข้อมูลพื้นฐานเกี่ยวกับส่วนแทรก
เมื่อแอปแสดงแบบเต็มหน้าจอ คุณต้องตรวจสอบว่า UI ของระบบไม่บดบังเนื้อหาและการโต้ตอบที่สําคัญ เช่น หากวางปุ่มไว้ด้านหลังแถบนําทาง ผู้ใช้อาจคลิกปุ่มนั้นไม่ได้
ขนาดของ UI ของระบบและข้อมูลเกี่ยวกับตําแหน่งที่จะวาง UI นั้นระบุผ่านส่วนเกิน
ส่วนต่างๆ ของ UI ของระบบมีข้อมูลแทรกประเภทที่เกี่ยวข้องซึ่งอธิบายขนาดและตำแหน่งของส่วนนั้นๆ ตัวอย่างเช่น ข้อมูลแทรกของแถบสถานะจะระบุขนาดและตําแหน่งของแถบสถานะ ส่วนข้อมูลแทรกของแถบนําทางจะระบุขนาดและตําแหน่งของแถบนําทาง ข้อมูลแทรกแต่ละประเภทประกอบด้วยมิติข้อมูลพิกเซล 4 รายการ ได้แก่ ด้านบน ซ้าย ขวา และด้านล่าง มิติข้อมูลเหล่านี้ระบุระยะที่ UI ของระบบยื่นออกมาจากด้านที่เกี่ยวข้องของหน้าต่างแอป ดังนั้น UI ของแอปจึงต้องฝังเข้าไปเป็นจำนวนดังกล่าวเพื่อไม่ให้ทับซ้อนกับ UI ของระบบประเภทนั้น
ประเภทอินเซ็ตในตัวของ Android ที่พร้อมใช้งานผ่าน WindowInsets
มีดังนี้
ส่วนที่เป็นภาพประกอบที่อธิบายแถบสถานะ แถบเหล่านี้คือแถบ UI ของระบบด้านบนที่มีไอคอนการแจ้งเตือนและตัวบ่งชี้อื่นๆ |
|
แถบสถานะจะฝังอยู่เมื่อมองเห็น หากขณะนี้แถบสถานะซ่อนอยู่ (เนื่องจากเข้าสู่โหมดเต็มหน้าจอแบบสมจริง) ส่วนแทรกของแถบสถานะหลักจะว่างเปล่า แต่ส่วนแทรกเหล่านี้จะไม่ว่างเปล่า |
|
ส่วนที่เป็นภาพประกอบอธิบายแถบนําทาง แถบเหล่านี้คือแถบ UI ของระบบทางด้านซ้าย ขวา หรือด้านล่างของอุปกรณ์ ซึ่งอธิบายแถบงานหรือไอคอนการนำทาง ซึ่งอาจเปลี่ยนแปลงขณะรันไทม์ตามวิธีการไปยังส่วนต่างๆ ที่ผู้ใช้ต้องการและการโต้ตอบกับแถบงาน |
|
แถบนำทางจะฝังอยู่เมื่อมองเห็น หากขณะนี้แถบนำทางซ่อนอยู่ (เนื่องจากเข้าสู่โหมดเต็มหน้าจอที่สมจริง) ส่วนแทรกของแถบนำทางหลักจะว่างเปล่า แต่ส่วนแทรกเหล่านี้จะไม่ว่างเปล่า |
|
ส่วนที่เป็นภาพแทรกที่อธิบายการตกแต่งหน้าต่าง UI ของระบบหากอยู่ในหน้าต่างรูปแบบอิสระ เช่น แถบชื่อด้านบน |
|
แถบคำบรรยายจะฝังอยู่เมื่อปรากฏ หากตอนนี้แถบคำบรรยายแทนเสียงซ่อนอยู่ ส่วนย่อยของแถบคำบรรยายแทนเสียงหลักจะว่างเปล่า แต่ส่วนย่อยเหล่านี้จะไม่ว่างเปล่า |
|
การรวมส่วนแทรกของแถบระบบ ซึ่งรวมถึงแถบสถานะ แถบนําทาง และแถบคำบรรยายแทนเสียง |
|
แถบระบบจะฝังอยู่เมื่อมองเห็น หากตอนนี้แถบระบบซ่อนอยู่ (เนื่องจากเข้าสู่โหมดเต็มหน้าจอแบบสมจริง) ส่วนแทรกของแถบระบบหลักจะว่างเปล่า แต่ส่วนแทรกเหล่านี้จะไม่ว่างเปล่า |
|
ส่วนแทรกที่อธิบายพื้นที่ด้านล่างที่แป้นพิมพ์ซอฟต์แวร์ใช้ |
|
ส่วนที่เป็นภาพตัดแสดงพื้นที่ที่แป้นพิมพ์ซอฟต์แวร์ใช้ก่อนภาพเคลื่อนไหวของแป้นพิมพ์ปัจจุบัน |
|
ส่วนที่เป็นภาพตัดแสดงพื้นที่ที่แป้นพิมพ์ซอฟต์แวร์จะครอบครองหลังจากภาพเคลื่อนไหวของแป้นพิมพ์ปัจจุบัน |
|
ประเภทของส่วนแทรกที่อธิบายข้อมูลโดยละเอียดเพิ่มเติมเกี่ยวกับ UI การนําทาง ซึ่งระบุพื้นที่ที่ระบบจะจัดการ "การแตะ" ไม่ใช่แอป สำหรับแถบนําทางแบบโปร่งใสที่มีการนําทางด้วยท่าทางสัมผัส ผู้ใช้สามารถแตะองค์ประกอบบางอย่างของแอปผ่าน UI การนําทางของระบบได้ |
|
องค์ประกอบที่แตะได้จะฝังอยู่เมื่อมองเห็น หากตอนนี้องค์ประกอบที่แตะได้ซ่อนอยู่ (เนื่องจากเข้าสู่โหมดเต็มหน้าจอที่สมจริง) ส่วนย่อยขององค์ประกอบที่แตะได้หลักจะว่างเปล่า แต่ส่วนย่อยเหล่านี้จะไม่ว่างเปล่า |
|
ส่วนที่ยื่นออกมาแสดงจำนวนส่วนที่ยื่นออกมาที่ระบบจะขัดจังหวะท่าทางสัมผัสสำหรับการไปยังส่วนต่างๆ แอปสามารถระบุการจัดการท่าทางสัมผัสเหล่านี้ในจำนวนที่จำกัดด้วยตนเองผ่าน |
|
ท่าทางสัมผัสของระบบชุดย่อยที่ระบบจะจัดการเสมอ และเลือกไม่ใช้ผ่าน |
|
ส่วนที่เป็นขอบแสดงถึงระยะห่างที่จําเป็นเพื่อหลีกเลี่ยงการซ้อนทับกับรอยบากของจอแสดงผล (รอยบากหรือรูเล็ก ๆ) |
|
ส่วนที่เป็นภาพตัดแสดงพื้นที่โค้งของการแสดงผล Waterfall การแสดงผล Waterfall จะมีพื้นที่โค้งตามขอบของหน้าจอที่หน้าจอเริ่มโค้งไปตามด้านข้างของอุปกรณ์ |
ประเภทเหล่านี้จะสรุปเป็นประเภทโฆษณาซ้อนใน "ปลอดภัย" 3 ประเภทต่อไปนี้เพื่อให้มั่นใจว่าเนื้อหาจะไม่ถูกบดบัง
ประเภทเนื้อหาที่ฝัง "ปลอดภัย" เหล่านี้จะปกป้องเนื้อหาด้วยวิธีต่างๆ โดยอิงตามเนื้อหาที่ฝังของแพลตฟอร์มพื้นฐาน ดังนี้
- ใช้
WindowInsets.safeDrawing
เพื่อปกป้องเนื้อหาที่ไม่ควรวาดไว้ใต้ UI ของระบบ การใช้งานที่พบบ่อยที่สุดของส่วนตัดคือเพื่อป้องกันไม่ให้วาดเนื้อหาที่ถูกบดบังโดย UI ของระบบ (บางส่วนหรือทั้งหมด) - ใช้
WindowInsets.safeGestures
เพื่อปกป้องเนื้อหาด้วยท่าทางสัมผัส วิธีนี้จะช่วยป้องกันไม่ให้ท่าทางสัมผัสของระบบขัดแย้งกับท่าทางสัมผัสของแอป (เช่น ท่าทางสัมผัสสำหรับชีตด้านล่าง ภาพสไลด์ หรือในเกม) - ใช้
WindowInsets.safeContent
ร่วมกับWindowInsets.safeDrawing
และWindowInsets.safeGestures
เพื่อให้เนื้อหาไม่มีภาพซ้อนทับและท่าทางสัมผัสซ้อนทับ
การตั้งค่าส่วนแทรก
หากต้องการให้แอปควบคุมตําแหน่งที่จะวาดเนื้อหาได้อย่างเต็มที่ ให้ทําตามขั้นตอนการตั้งค่าต่อไปนี้ หากไม่ทำตามขั้นตอนเหล่านี้ แอปอาจวาดสีดำหรือสีพื้นหลัง UI ของระบบ หรือภาพเคลื่อนไหวไม่ซิงค์กับแป้นพิมพ์ซอฟต์แวร์
- กําหนดเป้าหมายเป็น SDK 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 APIs
เมื่อกิจกรรมของคุณควบคุมการจัดการส่วนเกินทั้งหมดแล้ว คุณจะใช้ 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 แสดงภาพเคลื่อนไหวจนหมด
ลักษณะการทำงานนี้เกิดขึ้นจากการสื่อสารระหว่างตัวปรับเปลี่ยน 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 เฟรม ตัวปรับเปลี่ยนในตัวที่อธิบายไว้ในหน้านี้สร้างขึ้นเพื่อเลื่อนเวลาการใช้ค่าของส่วนตัดจนกว่าจะถึงระยะการวางเลย์เอาต์ ซึ่งช่วยให้มั่นใจได้ว่าระบบจะใช้ค่าของส่วนตัดในเฟรมเดียวกันกับที่อัปเดต
ภาพเคลื่อนไหวของ IME บนแป้นพิมพ์ที่มี WindowInsets
คุณสามารถใช้ Modifier.imeNestedScroll()
กับคอนเทนเนอร์ที่เลื่อนได้เพื่อเปิดและปิด IME โดยอัตโนมัติเมื่อเลื่อนไปที่ด้านล่างของคอนเทนเนอร์
class WindowInsetsExampleActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) WindowCompat.setDecorFitsSystemWindows(window, false) setContent { MaterialTheme { MyScreen() } } } } @OptIn(ExperimentalLayoutApi::class) @Composable fun MyScreen() { Box { LazyColumn( modifier = Modifier .fillMaxSize() // fill the entire window .imePadding() // padding for the bottom for the IME .imeNestedScroll(), // scroll IME at the bottom content = { } ) FloatingActionButton( modifier = Modifier .align(Alignment.BottomEnd) .padding(16.dp) // normal 16dp of padding for FABs .navigationBarsPadding() // padding for navigation bar .imePadding(), // padding for when IME appears onClick = { } ) { Icon(imageVector = Icons.Filled.Add, contentDescription = "Add") } } }
การรองรับการฝังสำหรับคอมโพเนนต์ Material 3
คอมโพสิชัน Material 3 ในตัวจำนวนมาก (androidx.compose.material3
) จะจัดการส่วนเกินด้วยตัวเองตามความสะดวกในการใช้งาน โดยอิงตามวิธีที่วางคอมโพสิชันในแอปตามข้อกำหนดของ Material
การจัดการคอมโพเนนต์ที่ประกอบกันได้ในอินเซ็ต
ด้านล่างนี้คือรายการคอมโพเนนต์ของ Material ที่จัดการส่วนเกินโดยอัตโนมัติ
แถบแอป
TopAppBar
/SmallTopAppBar
/CenterAlignedTopAppBar
/MediumTopAppBar
/LargeTopAppBar
: ใช้ด้านด้านบนและแนวนอนของแถบระบบเป็นระยะห่างจากขอบ เนื่องจากแถบดังกล่าวใช้ที่ด้านบนของหน้าต่างBottomAppBar
: ใช้ด้านด้านล่างและแนวนอนของแถบระบบเป็นระยะห่างจากขอบ
คอนเทนเนอร์เนื้อหา
ModalDrawerSheet
/DismissibleDrawerSheet
/PermanentDrawerSheet
(เนื้อหาภายในลิ้นชักการนำทางแบบโมดัล): ใช้ส่วนแทรกแนวตั้งและเริ่มต้นกับเนื้อหาModalBottomSheet
: ใช้ระยะห่างจากขอบด้านล่างNavigationBar
: ใช้การฝังด้านล่างและแนวนอนNavigationRail
: ใช้การเยื้องแนวตั้งและเริ่มต้น
Scaffold
โดยค่าเริ่มต้น
Scaffold
จะใส่ข้อมูลแทรกเป็นพารามิเตอร์ paddingValues
ให้คุณนำไปใช้
Scaffold
จะไม่ใส่ข้อมูลแทรกในเนื้อหา แต่เป็นหน้าที่ของคุณ
ตัวอย่างเช่น หากต้องการใช้ส่วนตัดเหล่านี้ที่มี LazyColumn
ภายใน Scaffold
ให้ทำดังนี้
Scaffold { innerPadding -> // innerPadding contains inset information for you to use and apply LazyColumn( // consume insets as scaffold doesn't do it by default modifier = Modifier.consumeWindowInsets(innerPadding), contentPadding = innerPadding ) { items(count = 100) { Box( Modifier .fillMaxWidth() .height(50.dp) .background(colors[it % colors.size]) ) } } }
ลบล้างระยะขอบเริ่มต้น
คุณสามารถเปลี่ยนพารามิเตอร์ windowInsets
ที่ส่งไปยังคอมโพสิเบิลเพื่อกําหนดค่าลักษณะการทํางานของคอมโพสิเบิลได้ พารามิเตอร์นี้อาจเป็นส่วนโค้งมนของหน้าต่างประเภทอื่นที่จะนําไปใช้แทน หรือปิดใช้โดยการส่งอินสแตนซ์ว่างเปล่า WindowInsets(0, 0, 0, 0)
ตัวอย่างเช่น หากต้องการปิดใช้การจัดการส่วนเกินใน LargeTopAppBar
ให้ตั้งค่าพารามิเตอร์ windowInsets
เป็นอินสแตนซ์ว่าง ดังนี้
LargeTopAppBar( windowInsets = WindowInsets(0, 0, 0, 0), title = { Text("Hi") } )
การทํางานร่วมกันกับส่วนแทรกของระบบ View
คุณอาจต้องลบล้างส่วนเกินเริ่มต้นเมื่อหน้าจอมีทั้งมุมมองและโค้ดการเขียนในลําดับชั้นเดียวกัน ในกรณีนี้ คุณต้องระบุอย่างชัดเจนว่าชิ้นงานใดควรใช้ส่วนแทรก และชิ้นงานใดควรละเว้น
เช่น หากเลย์เอาต์ด้านนอกสุดคือเลย์เอาต์ View ของ Android คุณควรใช้ส่วนตัดในระบบ View และละเว้นส่วนตัดใน Compose
หรือหากเลย์เอาต์ด้านนอกสุดเป็นคอมโพสิเบิล คุณควรใช้ส่วนเยื้องใน Compose และเพิ่มระยะห่างให้กับคอมโพสิเบิล AndroidView
ตามนั้น
โดยค่าเริ่มต้น ComposeView
แต่ละรายการจะใช้อินเซ็ตทั้งหมดในระดับการบริโภค WindowInsetsCompat
หากต้องการเปลี่ยนลักษณะการทำงานเริ่มต้นนี้ ให้ตั้งค่า ComposeView.consumeWindowInsets
เป็น false
การปกป้องแถบระบบ
เมื่อแอปกำหนดเป้าหมายเป็น SDK 35 ขึ้นไป ระบบจะบังคับใช้การแสดงผลแบบไร้ขอบ แถบสถานะของระบบและแถบการนำทางด้วยท่าทางสัมผัสจะโปร่งใส แต่แถบนำทางแบบ 3 ปุ่มจะโปร่งแสง
หากต้องการนำการป้องกันพื้นหลังการนำทางแบบ 3 ปุ่มที่โปร่งแสงเริ่มต้นออก ให้ตั้งค่า Window.setNavigationBarContrastEnforced
เป็น false
แหล่งข้อมูล
- แถบระบบ Android คำแนะนำเกี่ยวกับการออกแบบแถบระบบ
- พร้อมใช้งานใน Android แล้ว — แอป Android ที่ใช้งานได้อย่างเต็มรูปแบบซึ่งสร้างขึ้นด้วย Kotlin และ Jetpack Compose ทั้งหมด
- จัดการการบังคับใช้แบบเต็มหน้าจอใน Android 15 - Codelab ที่อธิบายการบังคับใช้แบบเต็มหน้าจอใน Android 15
- เคล็ดลับการจัดการส่วนเกินสำหรับการใช้พื้นที่หน้าจอจากขอบถึงขอบของ Android 15
- ดูตัวอย่างและทดสอบ UI แบบเต็มหน้าจอของแอป
- 3 วิธีปรับปรุงประสบการณ์การใช้งานแอป Android: การแสดงผลแบบเต็มหน้าจอ การคาดคะเนการย้อนกลับ และข้อมูลโดยย่อ — วิดีโอ YouTube ที่พูดถึงการบังคับใช้การแสดงผลแบบเต็มหน้าจอใน Android 15
- ภาพแบบเต็มหน้าจอและภาพส่วนเกิน | เคล็ดลับการคอมโพส - วิดีโอ YouTube ที่แสดงวิธีจัดการภาพส่วนเกินเพื่อวาดภาพแบบเต็มหน้าจอ
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- คอมโพเนนต์และเลย์เอาต์ของ Material Design
- ย้ายข้อมูล
CoordinatorLayout
ไปยัง "เขียน" - ข้อควรพิจารณาอื่นๆ