การใช้ 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()
เพื่อ
บันทึกสถานะเริ่มต้น
ข้อมูลโค้ดต่อไปนี้แสดงการเรียกใช้ 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
จะเรียกใช้เมื่อภาพเคลื่อนไหวของระยะขอบเริ่มต้น คุณใช้เพื่อตั้งค่าพร็อพเพอร์ตี้มุมมองทั้งหมด
เป็นสถานะสุดท้ายของการเปลี่ยนแปลงเลย์เอาต์ได้ หากคุณตั้งค่าการเรียกกลับ
OnApplyWindowInsetsListener
ไว้ในมุมมองใดก็ตาม ระบบจะเรียกใช้
ที่จุดนี้ ตอนนี้เป็นเวลาที่เหมาะในการบันทึกสถานะสุดท้ายของพร็อพเพอร์ตี้มุมมอง

onStart()
เพื่อบันทึก
สถานะสุดท้าย
ข้อมูลโค้ดต่อไปนี้แสดงการเรียกใช้ 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()
เพื่อ
ซิงค์ภาพเคลื่อนไหว
ข้อมูลโค้ดต่อไปนี้แสดงการเรียกใช้ 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