การใช้ WindowInsetsCompat
แอปสามารถค้นหาและควบคุมแป้นพิมพ์บนหน้าจอ (หรือที่เรียกว่า
IME) คล้ายกับ
วิธีที่ผู้ใช้โต้ตอบกับแถบของระบบ นอกจากนี้ แอปยังสามารถใช้
WindowInsetsAnimationCompat
เพื่อสร้างการเปลี่ยนที่ราบรื่นเมื่อเปิดหรือปิดแป้นพิมพ์ซอฟต์แวร์
สิ่งที่ต้องมีก่อน
ก่อนตั้งค่าการควบคุมและภาพเคลื่อนไหวสำหรับซอฟต์แวร์แป้นพิมพ์ ให้กำหนดค่า แอปของคุณให้แสดงแบบขอบต่อขอบ ซึ่งช่วยให้ จะจัดการกับส่วนต่างๆ ของหน้าต่างระบบ เช่น แถบระบบและแป้นพิมพ์บนหน้าจอ
ตรวจสอบการเปิดเผยซอฟต์แวร์แป้นพิมพ์
ใช้ WindowInsets
เพื่อตรวจสอบซอฟต์แวร์
การแสดงแป้นพิมพ์
Kotlin
val insets = ViewCompat.getRootWindowInsets(view) ?: return val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime()) val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
Java
WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(view); boolean imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime()); int imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom;
อีกวิธีหนึ่งคือ
ViewCompat.setOnApplyWindowInsetsListener
เพื่อสังเกตการเปลี่ยนแปลงการแสดงซอฟต์แวร์แป้นพิมพ์
Kotlin
ViewCompat.setOnApplyWindowInsetsListener(view) { _, insets -> val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime()) val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom insets }
Java
ViewCompat.setOnApplyWindowInsetsListener(view, (v, insets) -> { boolean imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime()); int imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom; return insets; });
ซิงค์ภาพเคลื่อนไหวกับซอฟต์แวร์แป้นพิมพ์
ผู้ใช้แตะช่องป้อนข้อความจะทำให้แป้นพิมพ์เลื่อนเข้าที่จาก ด้านล่างของหน้าจอ ดังที่แสดงในตัวอย่างต่อไปนี้
ตัวอย่างที่มีป้ายกำกับ "ไม่ซิงค์" ในรูปที่ 2 แสดงลักษณะการทำงานเริ่มต้น ใน Android 10 (API ระดับ 29) ซึ่งช่องข้อความและเนื้อหาของแอป สลับให้เข้าที่ แทนที่จะซิงค์กับแป้นพิมพ์ ภาพเคลื่อนไหว - พฤติกรรมที่อาจรบกวนสายตา
ใน Android 11 (API ระดับ 30) ขึ้นไป คุณสามารถใช้
WindowInsetsAnimationCompat
เพื่อซิงค์ข้อมูลการเปลี่ยนแปลงของแอปกับ แป้นพิมพ์เลื่อนขึ้นและลงจากด้านล่างของหน้าจอ ลุคนี้ นุ่มนวลขึ้น ดังที่แสดงในตัวอย่างชื่อ "ซิงค์แล้ว" ในรูปที่ 2
กำหนดค่า
WindowInsetsAnimationCompat.Callback
กับมุมมองที่จะซิงค์กับภาพเคลื่อนไหวของแป้นพิมพ์
Kotlin
ViewCompat.setWindowInsetsAnimationCallback( view, object : WindowInsetsAnimationCompat.Callback(DISPATCH_MODE_STOP) { // Override methods. } )
Java
ViewCompat.setWindowInsetsAnimationCallback( view, new WindowInsetsAnimationCompat.Callback( WindowInsetsAnimationCompat.Callback.DISPATCH_MODE_STOP ) { // Override methods. });
การลบล้างใน WindowInsetsAnimationCompat.Callback
ทำได้หลายวิธี
ได้แก่
onPrepare()
,
onStart()
,
onProgress()
และ
onEnd()
เริ่มด้วยการเรียกใช้ onPrepare()
ก่อนที่เลย์เอาต์ใดๆ จะเปลี่ยนแปลง
มีการเรียก onPrepare
เมื่อภาพเคลื่อนไหวประกอบเริ่มและก่อนการดู
วางเลเยอร์ใหม่
เพราะเป็นภาพเคลื่อนไหว คุณสามารถใช้เทมเพลตนี้เพื่อบันทึกสถานะเริ่มต้นได้
ซึ่งในกรณีนี้คือพิกัดด้านล่างของมุมมอง
ข้อมูลโค้ดต่อไปนี้แสดงตัวอย่างการโทรไปยัง onPrepare
Kotlin
var startBottom = 0f override fun onPrepare( animation: WindowInsetsAnimationCompat ) { startBottom = view.bottom.toFloat() }
Java
float startBottom; @Override public void onPrepare( @NonNull WindowInsetsAnimationCompat animation ) { startBottom = view.getBottom(); }
ระบบจะเรียก onStart
เมื่อภาพเคลื่อนไหวประกอบเริ่มต้นขึ้น คุณสามารถใช้การตั้งค่านี้เพื่อตั้งค่าทั้งหมด
คุณสมบัติมุมมองเป็นสถานะสิ้นสุดของเค้าโครงจะเปลี่ยนไป หากคุณมี
ตั้งค่า Callback OnApplyWindowInsetsListener
เป็นมุมมองใดก็ได้แล้ว
ในขั้นตอนนี้ นี่คือช่วงเวลาที่ดีในการบันทึกสถานะสิ้นสุดของมุมมอง
พร็อพเพอร์ตี้
ข้อมูลโค้ดต่อไปนี้แสดงตัวอย่างการโทรไปยัง onStart
Kotlin
var endBottom = 0f override fun onStart( animation: WindowInsetsAnimationCompat, bounds: WindowInsetsAnimationCompat.BoundsCompat ): WindowInsetsAnimationCompat.BoundsCompat { // Record the position of the view after the IME transition. endBottom = view.bottom.toFloat() return bounds }
Java
float endBottom; @NonNull @Override public WindowInsetsAnimationCompat.BoundsCompat onStart( @NonNull WindowInsetsAnimationCompat animation, @NonNull WindowInsetsAnimationCompat.BoundsCompat bounds ) { endBottom = view.getBottom(); return bounds; }
ระบบจะเรียก onProgress
เมื่อส่วนประกอบเปลี่ยนไปเป็นส่วนหนึ่งของการเรียกใช้ภาพเคลื่อนไหว
คุณจึงลบล้างและรับการแจ้งเตือนในทุกเฟรมบนแป้นพิมพ์ได้
ภาพเคลื่อนไหว อัปเดตคุณสมบัติของมุมมองเพื่อให้มุมมองมีการเคลื่อนไหวใน
กำลังซิงค์กับแป้นพิมพ์
ตอนนี้การเปลี่ยนแปลงเลย์เอาต์ทั้งหมดเสร็จสมบูรณ์แล้ว ตัวอย่างเช่น หากคุณใช้
View.translationY
เพื่อเปลี่ยนมุมมอง ค่าจะค่อยๆ ลดลงสำหรับทุกๆ
ของวิธีนี้ และในที่สุดจะถึง 0
ไปยังตำแหน่งเลย์เอาต์เดิม
ข้อมูลโค้ดต่อไปนี้แสดงตัวอย่างการโทรไปยัง onProgress
Kotlin
override fun onProgress( insets: WindowInsetsCompat, runningAnimations: MutableList<WindowInsetsAnimationCompat> ): WindowInsetsCompat { // Find an IME animation. val imeAnimation = runningAnimations.find { it.typeMask and WindowInsetsCompat.Type.ime() != 0 } ?: return insets // Offset the view based on the interpolated fraction of the IME animation. view.translationY = (startBottom - endBottom) * (1 - imeAnimation.interpolatedFraction) return insets }
Java
@NonNull @Override public WindowInsetsCompat onProgress( @NonNull WindowInsetsCompat insets, @NonNull List<WindowInsetsAnimationCompat> runningAnimations ) { // Find an IME animation. WindowInsetsAnimationCompat imeAnimation = null; for (WindowInsetsAnimationCompat animation : runningAnimations) { if ((animation.getTypeMask() & WindowInsetsCompat.Type.ime()) != 0) { imeAnimation = animation; break; } } if (imeAnimation != null) { // Offset the view based on the interpolated fraction of the IME animation. view.setTranslationY((startBottom - endBottom) * (1 - imeAnimation.getInterpolatedFraction())); } return insets; }
หรือคุณจะลบล้าง onEnd
ก็ได้ ระบบจะเรียกเมธอดนี้หลังจากภาพเคลื่อนไหว
จบแล้ว นี่คือช่วงเวลาที่ดีในการแก้ไขการเปลี่ยนแปลงที่เกิดขึ้นชั่วคราว
แหล่งข้อมูลเพิ่มเติม
- WindowInsetsAnimation ใน GitHub