باستخدام 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.