باستخدام 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
عند بدء رسم متحرك داخلي وقبل المشاهدات
تتم إعادة وضعها بسبب رسم متحرك. يمكنك استخدامه لحفظ حالة البدء،
وهو في هذه الحالة الإحداثيات السفلية للعرض.
![صورة توضّح الإحداثي السفلي لحالة البدء لعرض الجذر.](https://developer.android.com/static/images/guide/navigation/software-keyboard-3.png?authuser=19&hl=ar)
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
على أي من طرق العرض، سبق أن تم ضبطها.
في هذه المرحلة. هذا هو الوقت المناسب لحفظ حالة انتهاء العرض
المواقع.
![صورة تعرض الإحداثيات السفلية لحالة النهاية](https://developer.android.com/static/images/guide/navigation/software-keyboard-4.png?authuser=19&hl=ar)
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.