باستخدام أداة 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 (المستوى 29 لواجهة برمجة التطبيقات)، والذي فيه ينبثق الحقل النصي ومحتوى التطبيق في مكانه بدلاً من المزامنة مع الرسوم المتحركة للوحة المفاتيح - السلوك الذي قد يكون مزعجًا بصريًا.
في Android 11 (المستوى 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
عند بدء تشغيل صورة متحركة داخلية. يمكنك استخدامه لضبط جميع خصائص طريقة العرض
على الحالة النهائية لتغييرات التخطيط. إذا كانت لديك استدعاء
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.