באמצעות 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
מופעלת כשאנימציית השוליים הפנימיים מתחילה. אפשר להשתמש בו כדי להגדיר את כל מאפייני התצוגה למצב הסופי של שינויי הפריסה. אם הגדרתם קריאה חוזרת (callback) של 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.