نظرة عامة على الصور المتحركة للموقع

تجربة طريقة الإنشاء
Jetpack Compose هي مجموعة أدوات واجهة المستخدم المقترَحة لنظام التشغيل Android. تعرَّف على كيفية استخدام الصور المتحركة في ميزة Compose.

يُعد نظام الصور المتحركة للخصائص إطارًا قويًا يتيح لك تحريك أي شيء تقريبًا. يمكنك تحديد حركة لتغيير أي خاصية من عناصر الكائن بمرور الوقت، بغض النظر عما إذا كانت ستظهر على الشاشة أم لا. تؤدي الحركة للخاصية إلى تغيير قيمة السمة (حقل في عنصر) خلال مدة زمنية محدّدة. لإضافة تأثيرات حركية إلى عنصر، عليك تحديد سمة الكائن التي تريد تحريكها، مثل موضع العنصر على الشاشة والمدة التي تريد إنشاء الرسم فيها والقيم التي تريد إضافة تأثيرات حركية إليها.

يتيح لك نظام الصور المتحركة للسمات تحديد الخصائص التالية للصورة المتحركة:

  • المدة: يمكنك تحديد مدة الرسم المتحرك. المدة التلقائية هي 300 ملي ثانية.
  • استيفاء الوقت: يمكنك تحديد طريقة احتساب قيم السمة كدالة للوقت المنقضي الحالي للصورة المتحركة.
  • عدد التكرارات والسلوك: يمكنك تحديد ما إذا كنت تريد أن يتم تكرار الحركة عند وصولها إلى نهاية المدة وعدد مرات تكرار الصورة المتحركة. ويمكنك أيضًا تحديد ما إذا كنت تريد إعادة تشغيل الصورة المتحركة بالعكس. وعند ضبطها على الوضع العكسي، يتم تشغيل الصورة المتحركة للأمام ثم للخلف بشكل متكرّر إلى أن يتم الوصول إلى عدد التكرارات.
  • مجموعات أدوات الصور المتحركة: يمكنك تجميع الصور المتحركة في مجموعات منطقية يتم تشغيلها معًا أو بشكل تسلسلي أو بعد تأخيرات محدّدة.
  • مهلة تحديث الإطار: يمكنك تحديد عدد مرات تحديث الإطارات في الصورة المتحركة. ويتم ضبط الإعداد التلقائي على إعادة التحميل كل 10 ملي ثانية، ولكن السرعة التي يمكن لتطبيقك بها إعادة تحميل اللقطات تعتمد بشكل أساسي على مدى ازدحام النظام بشكل عام وسرعة النظام في تشغيل الموقّت الأساسي.

للاطّلاع على مثال كامل للسمات المتحركة، يمكنك الاطّلاع على الفئة ChangeColor في النموذج Customtransition على GitHub.

آلية عمل الرسوم المتحركة في الموقع

أولاً، لنستعرض كيفية عمل الرسوم المتحركة بمثال بسيط. يوضِّح الشكل 1 جسمًا افتراضيًا متحركًا باستخدام السمة x التي تمثِّل موقعه الأفقي على الشاشة. يتم ضبط مدة الصورة المتحركة على 40 ملي ثانية، بينما تبلغ المسافة التي يتم قطعها 40 بكسل. كل 10 ملي ثانية، وهو معدّل إعادة تحميل اللقطات التلقائي، يتحرك العنصر أفقيًا بمقدار 10 بكسل. في نهاية 40 ملي ثانية، تتوقف الصورة المتحركة وينتهي العنصر في الموضع الأفقي 40. هذا مثال على صورة متحرّكة تتضمّن استيفاءً خطيًا، ما يعني أنّ الجسم يتحرك بسرعة ثابتة.

الشكل 1. مثال على صورة متحركة خطية

ويمكنك أيضًا تحديد الرسوم المتحركة للحصول على استقراء غير خطي. يوضح الشكل 2 عنصرًا افتراضيًا يتسارع في بداية الصورة المتحركة، ويسرع في نهايته. لا يزال الكائن يتحرك 40 بكسل خلال 40 ملي ثانية، ولكن بشكل غير خطي. في البداية، يتم تسريع هذه الحركة حتى تصل إلى نقطة المنتصف، ثم تنخفض سرعتها من نقطة المنتصف حتى نهايتها. كما يبيّن الشكل 2، إنّ المسافة التي تم قطعها في بداية ونهاية الصورة المتحركة أقل من المسافة التي تم قطعها في المنتصف.

الشكل 2. مثال على صورة متحرّكة غير خطية

لنلقِ نظرة تفصيلية على طريقة احتساب المكوّنات المهمة لنظام الصور المتحركة مثل تلك الموضّحة أعلاه. يوضّح الشكل 3 طريقة عمل الصفوف الرئيسية مع بعضها البعض.

الشكل 3. طريقة احتساب الصور المتحركة

يتتبّع الكائن ValueAnimator توقيت الصورة المتحركة، مثل مدة تشغيل الصورة المتحركة والقيمة الحالية للسمة التي يحرّكها الصورة.

تحتوي السمة ValueAnimator على TimeInterpolator التي تحدّد استقراء الحركة، وقيمة TypeEvaluator التي تحدّد كيفية حساب قيم السمة التي يتم تحريكها. على سبيل المثال، في الشكل 2، ستكون قيمة TimeInterpolator المستخدَمة على شكل AccelerateDecelerateInterpolator وقيمة TypeEvaluator على IntEvaluator.

لبدء استخدام صورة متحركة، أنشِئ ValueAnimator وأضِف قيم البداية والنهاية للسمة التي تريد تحريكها، بالإضافة إلى مدة الحركة. عند استدعاء start()، تبدأ الرسوم المتحركة. أثناء تحريك الصورة المتحركة بالكامل، تحتسب ValueAnimator الكسر المنقضي بين 0 و1، وذلك استنادًا إلى مدة الصورة المتحركة والمدة المنقضية. ويمثّل الكسر المنقضي النسبة المئوية للوقت الذي اكتملت فيه الصورة المتحركة، حيث تشير القيمة 0 إلى %0 والرقم 1 إلى %100. على سبيل المثال، في الشكل 1، سيكون الكسر المنقضي عند t = 10 ملي ثانية يساوي .25 لأنّ المدة الإجمالية هي t = 40 ملي ثانية.

عند الانتهاء من احتساب ValueAnimator من الكسر المنقضي، يستدعي السمة TimeInterpolator المضبوطة حاليًا لاحتساب الكسر المُدخل. يربط الكسر المضاف على سبيل المثال، في الشكل 2، وبما أنّ الحركة المتحركة تتسارع ببطء، فإنّ الكسر المضاف، وهو حوالي 15.، أقل من الكسر المنقضي، 0.25، عند t = 10 ملي ثانية. وفي الشكل 1، يكون الكسر المضاف دائمًا هو نفسه الكسر المنقضي دائمًا.

عند حساب الكسر المُدخل، يستدعي ValueAnimator قيمة TypeEvaluator المناسبة لحساب قيمة الخاصية التي تحرّكها، استنادًا إلى الكسر المُدخل، وقيمة البداية، والقيمة النهائية للحركة. على سبيل المثال، في الشكل 2، كان الكسر المدمَج 0 .15 عند t = 10 ملي ثانية، وبالتالي تكون قيمة الموقع في ذلك الوقت .15 × (40 - 0) أو 6.

أوجه الاختلاف بين الرسوم المتحركة للمكان وبين الرسوم المتحركة للعرض

يتيح نظام عرض الصور المتحركة فقط تحريك كائنات View، لذا إذا أردت تحريك كائنات ليست View، عليك تنفيذ رمزك الخاص لإجراء ذلك. كما أنّ نظام العرض المتحركة يوفّر إمكانية تحريك بعض العناصر من الكائن View فقط، مثل تغيير حجم العرض وتدويره وليس لون الخلفية، على سبيل المثال.

ومن العيوب الأخرى لنظام العرض المتحرك أنّه تم تعديل موضع رسم العرض فقط وليس العرض الفعلي بحد ذاته. على سبيل المثال، إذا أضفت تأثيرات حركية إلى زر لنقله على الشاشة، سيتم رسم الزر بشكل صحيح، إلا أنّ الموقع الفعلي الذي يمكنك النقر فيه على الزر لن يتغيّر، لذا يجب أن تطبّق منطقك الخاص للتعامل مع هذا الأمر.

عند استخدام نظام الصور المتحركة للخصائص، تتم إزالة هذه القيود بالكامل، ويمكنك إضافة تأثير متحرك إلى أي خاصية من أي كائن (Views and non-Views) وتعديل العنصر نفسه. كما يعد نظام الرسوم المتحركة للخصائص أكثر قوة في طريقة تنفيذه للصور المتحركة. يمكنك تعيين أدوات متحركة للسمات التي تريد إضافتها، مثل اللون أو الموضع أو الحجم، كما يمكنك تحديد جوانب الحركة، مثل إضافة البيانات المتحركة ومزامنة أدوات الصور المتحركة المتعددة.

ومع ذلك، يستغرق نظام الرسوم المتحركة للعرض وقتًا أقل لإعداده ويتطلب رمزًا أقل للكتابة. إذا كانت الصورة المتحركة للعرض تنجز كل ما تحتاج إلى تنفيذه أو إذا كانت الرموز البرمجية الحالية تعمل بالطريقة التي تريدها، لن يكون عليك استخدام نظام الصور المتحركة للسمات. وقد يكون من المنطقي استخدام كلا نظامَي الصور المتحركة في مواقف مختلفة إذا نشأت حالة استخدام.

نظرة عامة على واجهة برمجة التطبيقات

يمكنك العثور على معظم واجهات برمجة التطبيقات لنظام الصور المتحركة في android.animation. بما أنّ نظام عرض الصور المتحركة يحدّد حاليًا العديد من أدوات الاستيفاء في android.view.animation، يمكنك استخدام هذه الأدوات في نظام الصور المتحركة للسمات أيضًا. توضّح الجداول التالية المكوّنات الرئيسية لنظام الصور المتحركة.

توفّر الفئة Animator البنية الأساسية لإنشاء الصور المتحركة. أنت لا تستخدم هذه الفئة في العادة بشكل مباشر، لأنّها توفّر فقط الحد الأدنى من الوظائف التي يجب توسيعها لإتاحة استخدام القيم المتحركة بشكل كامل. أمّا الفئات الفرعية التالية، فتُكمّل Animator:

الجدول 1. أدوات صناعة الصورة المتحركة

الفئة الوصف
ValueAnimator محرّك التوقيت الرئيسي لتحريك الخصائص، والذي يحتسب أيضًا قيم السمة المطلوب تحريكها. ويحتوي هذا النموذج على جميع الوظائف الأساسية التي تحتسب قيم الصور المتحركة، كما يحتوي على تفاصيل توقيت كل صورة متحركة، ومعلومات حول ما إذا كانت الرسوم المتحركة تتكرر، وأدوات الاستجابة التي تتلقى أحداث التحديث، وإمكانية تحديد أنواع مخصصة للتقييم. هناك قسمان للخصائص المتحركة، هما: حساب القيم المتحركة وضبط هذه القيم على الكائن والخاصية التي يتم تحريكها. ولا ينفّذ ValueAnimator الجزء الثاني، لذا يجب أن تستمع إلى التعديلات على القيم التي تحتسبها ValueAnimator، وأن تعدّل العناصر التي تريد تحريكها وفقًا لمنطقك الخاص. راجِع القسم حول الرسوم المتحركة باستخدام ValueAnimator للحصول على مزيد من المعلومات.
ObjectAnimator هي فئة فرعية من ValueAnimator تتيح لك ضبط خاصية كائن وكائن هدف لتحريكها. وتُعدِّل هذه الفئة السمة وفقًا لذلك عندما تحتسب قيمة جديدة للصورة المتحركة. ننصحك باستخدام ObjectAnimator معظم الوقت لأنّه يجعل عملية تحريك القيم المتحركة على العناصر المستهدفة أسهل كثيرًا. في المقابل، قد تحتاج أحيانًا إلى استخدام السمة ValueAnimator مباشرةً لأنّ السمة ObjectAnimator تفرض بعض القيود الإضافية، مثل طلب توفّر طرق وصول معيّنة في العنصر الهدف.
AnimatorSet توفر آلية لتجميع الصور المتحركة معًا بحيث تعمل في ضوء بعضها البعض. يمكنك ضبط الصور المتحركة لتشغيلها معًا، أو بشكل تسلسلي، أو بعد مهلة محددة. للحصول على مزيد من المعلومات، يمكنك الاطّلاع على القسم حول تصميم صور متحركة متعددة باستخدام مجموعات الرسوم المتحركة.

يُطلع المقيّمون نظام الصور المتحركة على كيفية احتساب قيم سمة معيّنة. وهي تستخدم بيانات التوقيت التي توفّرها الفئة Animator، وهي قيمة بداية ونهاية الصورة المتحركة، وتحسب القيم المتحركة للسمة بناءً على هذه البيانات. يوفر نظام الرسوم المتحركة للخصائص المقيّمين التاليين:

الجدول 2. المقيّمون

الصف/الواجهة الوصف
IntEvaluator المقيِّم التلقائي لحساب قيم خصائص int.
FloatEvaluator المقيِّم التلقائي لحساب قيم خصائص float.
ArgbEvaluator المقيِّم التلقائي لحساب قيم خصائص اللون التي يتم تمثيلها كقيم سداسية عشرية.
TypeEvaluator واجهة تسمح لك بإنشاء مقيّم خاص بك. إذا كنت تتحرك خاصية عنصر ليست int أو float أو لون، عليك تنفيذ واجهة TypeEvaluator لتحديد طريقة احتساب القيم المتحركة لخاصية الكائن. يمكنك أيضًا تحديد سمة TypeEvaluator مخصّصة لقيم int وfloat واللون إذا كنت تريد معالجة هذه الأنواع بطريقة مختلفة عن السلوك التلقائي. راجِع القسم حول استخدام مُقيّم النوع للحصول على مزيد من المعلومات حول كيفية كتابة مقيّم مخصّص.

تحدّد أداة استيفاء الوقت كيفية احتساب قيم معيّنة في إحدى الصور المتحركة كدالة للوقت. على سبيل المثال، يمكنك تحديد مؤثرات حركية لتنفيذها بشكل خطي في الصورة المتحركة بأكملها، أي أن الحركة تتحرك بالتساوي طوال الوقت، أو يمكنك تحديد حركات باستخدام زمن غير خطي، مثل تسريع الحركة في البداية والإبطاء في نهايتها. يوضّح الجدول 3 أدوات الاستيفاء المضمَّنة في android.view.animation. إذا لم يلائم أيٌّ من هذه الأدوات احتياجاتك، يمكنك تنفيذ واجهة TimeInterpolator وإنشاء الواجهة الخاصة بك. راجِع استخدام أداة الاستيفاء للحصول على مزيد من المعلومات عن كيفية كتابة أداة مخصّصة.

الجدول 3. متتبعو اختبارات

الصف/الواجهة الوصف
AccelerateDecelerateInterpolator أداة استقراء يبدأ معدّل تغيُّرها ببطء وينتهي ببطء، ولكن تتسرّعها من المنتصف.
AccelerateInterpolator أداة استقراء يبدأ معدّل تغيُّرها ببطء ثم يسرّعها.
AnticipateInterpolator أداة استقراء يبدأ تغييرها للخلف ثم ينتقل للأمام.
AnticipateOvershootInterpolator أداة احتساب، يبدأ التغيير في الرجوع إلى الخلف، ثم ينتقل إلى الأمام ويتجاوز القيمة المستهدفة، ثم يعود في النهاية إلى القيمة النهائية.
BounceInterpolator أداة استقراء ارتداد التغيير في النهاية.
CycleInterpolator أداة استقراء يتم تكرار حركتها لعدد محدّد من الدورات.
DecelerateInterpolator أداة استقراء يبدأ معدّل تغيُّرها بسرعة ثم يتراجع.
LinearInterpolator مُنتجِب ثابت معدّل تغيُّره.
OvershootInterpolator أداة احتساب، يدخل التغيير في الأمام ويتجاوز القيمة الأخيرة، ثم يعود.
TimeInterpolator هي واجهة تسمح لك بتنفيذ أداة الاستيفاء الخاصة بك.

أضِف تأثيرات متحركة باستخدام ValueAnimator

تتيح لك الفئة ValueAnimator إمكانية تحريك قيَم من نوع معيّن خلال مدة الحركة من خلال تحديد مجموعة من int أو float أو قيم لونية لتحريكها. يمكنك الحصول على ValueAnimator من خلال طلب إحدى الطرق الأصلية الخاصة بها: ofInt() أو ofFloat() أو ofObject(). مثال:

Kotlin

ValueAnimator.ofFloat(0f, 100f).apply {
    duration = 1000
    start()
}

Java

ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f);
animation.setDuration(1000);
animation.start();

في هذا الرمز، تبدأ ValueAnimator في احتساب قيم الحركة التي تتراوح بين 0 و100 لمدة 1,000 ملي ثانية عند تشغيل طريقة start().

يمكنك أيضًا تحديد نوع مخصص للتحريك من خلال إجراء ما يلي:

Kotlin

ValueAnimator.ofObject(MyTypeEvaluator(), startPropertyValue, endPropertyValue).apply {
    duration = 1000
    start()
}

Java

ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
animation.setDuration(1000);
animation.start();

في هذا الرمز، تبدأ ValueAnimator في احتساب قيم الحركة، بين startPropertyValue وendPropertyValue باستخدام المنطق المُقدَّم من MyTypeEvaluator لمدة 1,000 ملي ثانية، عند تشغيل الإجراء start().

يمكنك استخدام قيم الصورة المتحركة من خلال إضافة AnimatorUpdateListener إلى العنصر ValueAnimator على النحو الموضّح في الرمز التالي:

Kotlin

ValueAnimator.ofObject(...).apply {
    ...
    addUpdateListener { updatedAnimation ->
        // You can use the animated value in a property that uses the
        // same type as the animation. In this case, you can use the
        // float value in the translationX property.
        textView.translationX = updatedAnimation.animatedValue as Float
    }
    ...
}

Java

animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator updatedAnimation) {
        // You can use the animated value in a property that uses the
        // same type as the animation. In this case, you can use the
        // float value in the translationX property.
        float animatedValue = (float)updatedAnimation.getAnimatedValue();
        textView.setTranslationX(animatedValue);
    }
});

في الطريقة onAnimationUpdate()، يمكنك الوصول إلى قيمة الحركة المعدَّلة واستخدامها في سمة لأحد الملفات الشخصية. لمزيد من المعلومات حول المستمعين، يمكنك الاطّلاع على القسم حول أدوات معالجة الصور المتحركة.

أضِف تأثيرات متحركة باستخدام ObjectAnimator

ObjectAnimator هي فئة فرعية من ValueAnimator (تمت مناقشتها في القسم السابق) وتجمع بين محرّك التوقيت وحساب القيمة ValueAnimator مع إمكانية تحريك خاصية مُسمّاة لكائن مستهدَف. ويسهِّل ذلك إنشاء الصور المتحركة في أي عنصر لأنّك لم تعُد بحاجة إلى تنفيذ السمة ValueAnimator.AnimatorUpdateListener، لأنّه يتم تعديل السمة المتحركة تلقائيًا.

إنّ إنشاء ObjectAnimator يشبه العنصر ValueAnimator، ولكنّك تحدّد أيضًا الكائن واسم خاصية ذلك الكائن (كسلسلة) مع القيم المطلوب تحريكها بين:

Kotlin

ObjectAnimator.ofFloat(textView, "translationX", 100f).apply {
    duration = 1000
    start()
}

Java

ObjectAnimator animation = ObjectAnimator.ofFloat(textView, "translationX", 100f);
animation.setDuration(1000);
animation.start();

للحصول على سمات تعديل ObjectAnimator بشكل صحيح، عليك تنفيذ ما يلي:

  • يجب أن تحتوي خاصية الكائن التي تريد تحريكها على دالة setter (في حالة الجمل) وتكون بالتنسيق set<PropertyName>(). بما أنّ ObjectAnimator تعدِّل السمة تلقائيًا أثناء الحركة، يجب أن تتمكّن من الوصول إلى الموقع باستخدام طريقة الضبط هذه. على سبيل المثال، إذا كان اسم السمة هو foo، يجب استخدام الطريقة setFoo(). إذا لم تتوفّر طريقة الضبط هذه، لديك ثلاثة خيارات:
    • أضف طريقة setter إلى الفئة إذا كان لديك الحق في القيام بذلك.
    • استخدِم فئة برنامج تضمين لديك الحق في تغييرها واطلب من هذا البرنامج تلقّي القيمة باستخدام طريقة ضبط صالحة ثم أعِد توجيهها إلى الكائن الأصلي.
    • يمكنك استخدام ValueAnimator كبديل.
  • إذا حدّدت قيمة واحدة فقط للمعلَمة values... في إحدى طرق الإعدادات الأصلية لـ ObjectAnimator، يُفترض أن تكون القيمة النهائية للصورة المتحركة. وبالتالي، يجب أن تحتوي خاصية الكائن التي تريد تحريكها على دالة getter التي تُستخدَم للحصول على القيمة الافتتاحية الخاصة بالحركة. يجب أن تكون دالة getter بالصيغة get<PropertyName>(). على سبيل المثال، إذا كان اسم السمة هو foo، يجب استخدام طريقة getFoo().
  • يجب أن تعمل طريقتا getter (إذا لزم الأمر) وsetter للسمة التي تريد إنشاء رسوم متحركة لها بنفس نوع قيمتَي البداية والنهاية التي تحدِّدها للسمة ObjectAnimator. على سبيل المثال، يجب أن يتوفّر لديك targetObject.setPropName(float) وtargetObject.getPropName() إذا أنشأت علامة ObjectAnimator التالية:
    ObjectAnimator.ofFloat(targetObject, "propName", 1f)
    
    .
  • حسب الخاصية أو العنصر الذي تحرّكه، قد تحتاج إلى استدعاء طريقة invalidate() في أحد الملفات الشخصية لفرض إعادة رسم الشاشة باستخدام القيم المتحركة المعدّلة. يمكنك إجراء ذلك من خلال onAnimationUpdate(). على سبيل المثال، عند تحريك خاصية اللون لكائن قابل للرسم، يتم تطبيق تعديلات على الشاشة فقط عندما يعيد ذلك الكائن رسمه. إنّ جميع ضبط السمات في الملف الشخصي، مثل setAlpha() وsetTranslationX()، يؤدي إلى إبطال صلاحية العرض بشكلٍ صحيح، لذا لا تحتاج إلى إلغاء صلاحية العرض عند استدعاء هذه الطرق بقيم جديدة. لمزيد من المعلومات حول المستمعين، يمكنك الاطّلاع على القسم حول أدوات معالجة الصور المتحركة.

صمِّم صورًا متحركة متعددة باستخدام مجموعة AnimatorSet

في كثير من الأحيان، ستحتاج إلى تشغيل صورة متحركة تعتمد على وقت بدء صورة متحركة أخرى أو انتهائها. يتيح لك نظام Android تجميع الصور المتحركة معًا في AnimatorSet حتى تتمكّن من تحديد ما إذا كنت تريد بدء الصور المتحركة في وقت واحد أو بشكل تسلسلي أو بعد مهلة محددة. يمكنك أيضًا دمج عناصر AnimatorSet داخل بعضها.

يشغِّل مقتطف الرمز التالي كائنات Animator التالية بالطريقة التالية:

  1. تشغيل bounceAnim.
  2. يتم تشغيل squashAnim1 وsquashAnim2 وstretchAnim1 وstretchAnim2 في الوقت نفسه.
  3. تشغيل bounceBackAnim.
  4. تشغيل fadeAnim.

Kotlin

val bouncer = AnimatorSet().apply {
    play(bounceAnim).before(squashAnim1)
    play(squashAnim1).with(squashAnim2)
    play(squashAnim1).with(stretchAnim1)
    play(squashAnim1).with(stretchAnim2)
    play(bounceBackAnim).after(stretchAnim2)
}
val fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply {
    duration = 250
}
AnimatorSet().apply {
    play(bouncer).before(fadeAnim)
    start()
}

Java

AnimatorSet bouncer = new AnimatorSet();
bouncer.play(bounceAnim).before(squashAnim1);
bouncer.play(squashAnim1).with(squashAnim2);
bouncer.play(squashAnim1).with(stretchAnim1);
bouncer.play(squashAnim1).with(stretchAnim2);
bouncer.play(bounceBackAnim).after(stretchAnim2);
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(bouncer).before(fadeAnim);
animatorSet.start();

أدوات معالجة الرسوم المتحركة

يمكنك الاستماع إلى الأحداث المهمة خلال مدة الرسوم المتحركة مع المستمعين الموضحين أدناه.

  • Animator.AnimatorListener
    • onAnimationStart() - يتم استدعاءه عند بدء الصورة المتحركة.
    • onAnimationEnd() - يتم استدعاؤه عند انتهاء الصورة المتحركة.
    • onAnimationRepeat() - يتم استدعاؤه عند تكرار الصورة المتحركة نفسها.
    • onAnimationCancel() - يتم استدعاؤه عند إلغاء الصورة المتحركة. وتطلب الصورة المتحركة التي تم إلغاؤها أيضًا onAnimationEnd()، بغض النظر عن كيفية إنهائها.
  • ValueAnimator.AnimatorUpdateListener
    • onAnimationUpdate(): يتم طلب هذا الإجراء في كل إطار من الصورة المتحركة. يمكنك الاستماع إلى هذا الحدث لاستخدام القيم المحسوبة التي أنشأها ValueAnimator أثناء حركة. لاستخدام القيمة، يمكنك طلب البحث عن الكائن ValueAnimator الذي تم تمريره إلى الحدث للحصول على القيمة المتحركة الحالية باستخدام الإجراء getAnimatedValue(). يجب تنفيذ أداة الاستماع هذه إذا كنت تستخدم ValueAnimator.

      حسب الخاصية أو العنصر الذي تريد تحريكه، قد تحتاج إلى استدعاء invalidate() على "ملف شخصي" لفرض إعادة رسم تلك المنطقة من الشاشة باستخدام القيم المتحركة الجديدة. على سبيل المثال، عند تحريك خاصية اللون لكائن قابل للرسم فقط، لا يتم إجراء تعديلات على الشاشة إلا عندما يعيد ذلك الكائن رسمه. جميع قيم السمات التي تضبطها في الملف الشخصي، مثل setAlpha() وsetTranslationX()، تؤدي إلى إبطال صلاحية العرض بشكلٍ صحيح، لذا لا تحتاج إلى إلغاء صلاحية العرض عند استدعاء هذه الطرق بقيم جديدة.

يمكنك تمديد الفئة AnimatorListenerAdapter بدلاً من تنفيذ الواجهة Animator.AnimatorListener إذا لم تكن تريد تنفيذ جميع الطرق المستخدَمة في واجهة Animator.AnimatorListener. توفّر الفئة AnimatorListenerAdapter عمليات تنفيذ فارغة للطرق التي يمكنك اختيار تجاهلها.

على سبيل المثال، ينشئ مقتطف الرمز التالي AnimatorListenerAdapter لمعاودة الاتصال onAnimationEnd() فقط:

Kotlin

ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply {
    duration = 250
    addListener(object : AnimatorListenerAdapter() {
        override fun onAnimationEnd(animation: Animator) {
            balls.remove((animation as ObjectAnimator).target)
        }
    })
}

Java

ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
fadeAnim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
    balls.remove(((ObjectAnimator)animation).getTarget());
}

تحريك تغييرات التصميم لكائنات ViewGroup

يوفّر نظام الصور المتحركة للخصائص إمكانية تحريك التغييرات على كائنات ViewGroup، بالإضافة إلى توفير طريقة سهلة لتحريك عناصر View نفسها.

يمكنك إضافة تأثيرات حركية إلى تغييرات التنسيق داخل ViewGroup باستخدام الفئة LayoutTransition. يمكن أن تمر المشاهدات داخل مجموعة ViewGroup بصورة متحرّكة تظهر وتختفي عند إضافتها إلى مجموعة مشاهدة أو إزالتها منها أو عند طلب طريقة "setVisibility()" للملف الشخصي باستخدام VISIBLE أو INVISIBLE أو GONE. يمكن لطرق العرض المتبقية في ViewGroup أيضًا إضافة تأثيرات حركية إلى مواضعها الجديدة عند إضافة مشاهدات أو إزالتها. يمكنك تحديد الرسوم المتحركة التالية في كائن LayoutTransition من خلال استدعاء setAnimator() وتمرير كائن Animator بأحد ثوابت LayoutTransition التالية:

  • APPEARING - علامة تشير إلى أنّ الصورة المتحركة تعمل على العناصر التي تظهر في الحاوية.
  • CHANGE_APPEARING: علامة تشير إلى أنّ الصورة المتحركة تعمل على العناصر التي تتغير بسبب ظهور عنصر جديد في الحاوية.
  • DISAPPEARING - علامة تشير إلى تشغيل الصورة المتحركة على عناصر تختفي من الحاوية.
  • CHANGE_DISAPPEARING - علامة تشير إلى تشغيل الصورة المتحركة على عناصر تتغير بسبب اختفاء عنصر من الحاوية.

يمكنك تحديد صور متحركة مخصّصة لهذه الأنواع الأربعة من الأحداث من أجل تخصيص مظهر انتقالات التصميم، أو يمكنك إعلام نظام الصور المتحركة باستخدام الصور المتحركة التلقائية.

لضبط السمة android:animateLayoutchanges على true في ViewGroup، عليك اتّباع الخطوات التالية:

<LinearLayout
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:id="@+id/verticalContainer"
    android:animateLayoutChanges="true" />

عند ضبط هذه السمة على "صحيح"، يتم تلقائيًا نقل الملفات الشخصية التي تتم إضافتها أو إزالتها من "مجموعة المشاهدة" وكذلك الملفات الشخصية المتبقية في "مجموعة المشاهدة".

تحريك تغييرات حالة العرض باستخدام StateListAnimator

تتيح لك الفئة StateListAnimator تحديد أدوات الصور المتحركة التي يتم تشغيلها عندما تتغير حالة العرض. يعمل هذا الكائن كبرنامج تضمين لكائن Animator، حيث يستدعي هذه الصورة المتحركة كلما تغيّرت حالة العرض المحدّدة (مثل "مضغوط" أو "مركّز").

يمكن تحديد StateListAnimator في مورد XML باستخدام عنصر <selector> جذر وعناصر <item> ثانوية يحدّد كل منها حالة عرض مختلفة تحدّدها الفئة StateListAnimator. وتحتوي كل سمة <item> على تعريف مجموعة صور متحركة.

على سبيل المثال، يقوم الملف التالي بإنشاء قائمة حالة متحركة يقوم بتغيير المقياسين x وy للعرض عند الضغط عليهما:

res/xml/animate_scale.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- the pressed state; increase x and y size to 150% -->
    <item android:state_pressed="true">
        <set>
            <objectAnimator android:propertyName="scaleX"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="1.5"
                android:valueType="floatType"/>
            <objectAnimator android:propertyName="scaleY"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="1.5"
                android:valueType="floatType"/>
        </set>
    </item>
    <!-- the default, non-pressed state; set x and y size to 100% -->
    <item android:state_pressed="false">
        <set>
            <objectAnimator android:propertyName="scaleX"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="1"
                android:valueType="floatType"/>
            <objectAnimator android:propertyName="scaleY"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="1"
                android:valueType="floatType"/>
        </set>
    </item>
</selector>

لإرفاق الصورة المتحركة لقائمة الحالة بعرض، أضِف السمة android:stateListAnimator على النحو التالي:

<Button android:stateListAnimator="@xml/animate_scale"
        ... />

يتم الآن استخدام الرسوم المتحركة المحددة في animate_scale.xml عندما تتغير حالة هذا الزر.

أو بدلاً من ذلك، يمكنك تعيين أداة لصور متحرّكة لقائمة الحالات لعرض في الرمز، استخدِم طريقة AnimatorInflater.loadStateListAnimator()، وخصِّص أداة الصور المتحركة إلى العرض الخاص بك باستخدام طريقة View.setStateListAnimator().

أو بدلاً من تحريك خصائص طريقة العرض، يمكنك تشغيل صورة متحركة قابلة للرسم بين تغييرات الحالة باستخدام AnimatedStateListDrawable. تستخدم بعض أدوات النظام في Android 5.0 هذه الرسوم المتحركة بشكل افتراضي. يوضّح المثال التالي كيفية تحديد AnimatedStateListDrawable كمورد XML:

<!-- res/drawable/myanimstatedrawable.xml -->
<animated-selector
    xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- provide a different drawable for each state-->
    <item android:id="@+id/pressed" android:drawable="@drawable/drawableP"
        android:state_pressed="true"/>
    <item android:id="@+id/focused" android:drawable="@drawable/drawableF"
        android:state_focused="true"/>
    <item android:id="@id/default"
        android:drawable="@drawable/drawableD"/>

    <!-- specify a transition -->
    <transition android:fromId="@+id/default" android:toId="@+id/pressed">
        <animation-list>
            <item android:duration="15" android:drawable="@drawable/dt1"/>
            <item android:duration="15" android:drawable="@drawable/dt2"/>
            ...
        </animation-list>
    </transition>
    ...
</animated-selector>

استخدام مُقيِّم النوع

إذا كنت تريد إضافة تأثيرات حركية إلى نوع غير معروف لنظام Android، يمكنك إنشاء مقيّم خاص بك من خلال تنفيذ واجهة TypeEvaluator. الأنواع المعروفة لنظام Android هي int أو float أو لون متوافق مع مقيّمي الأنواع IntEvaluator وFloatEvaluator وArgbEvaluator.

هناك طريقة واحدة فقط للتنفيذ في واجهة TypeEvaluator، وهي طريقة evaluate(). ويسمح هذا لرسم الصور المتحركة الذي تستخدمه بعرض القيمة المناسبة لخاصيتك المتحركة في النقطة الحالية من الصورة المتحركة. تشرح الفئة FloatEvaluator كيفية إجراء ذلك:

Kotlin

private class FloatEvaluator : TypeEvaluator<Any> {

    override fun evaluate(fraction: Float, startValue: Any, endValue: Any): Any {
        return (startValue as Number).toFloat().let { startFloat ->
            startFloat + fraction * ((endValue as Number).toFloat() - startFloat)
        }
    }

}

Java

public class FloatEvaluator implements TypeEvaluator {

    public Object evaluate(float fraction, Object startValue, Object endValue) {
        float startFloat = ((Number) startValue).floatValue();
        return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
    }
}

ملاحظة: عند تشغيل ValueAnimator (أو ObjectAnimator)، يتم احتساب الكسر المنقضي حاليًا من الحركة (قيمة تتراوح بين 0 و1) ثم احتساب نسخة مُضافة منها بناءً على أداة الاستيفاء التي تستخدمها. الكسر المضاف هو ما يتلقّاه TypeEvaluator من خلال المَعلمة fraction، لذا لا يجب أن تأخذ في الاعتبار أداة الاستيفاء عند حساب القيم المتحركة.

استخدام أدوات الاستيفاء

يحدّد مقياس الاستيفاء كيفية احتساب القيم المحدّدة في إحدى الصور المتحركة كدالة للوقت. على سبيل المثال، يمكنك تحديد مؤثرات حركية ليتم عرضها بشكل خطي في الصورة المتحركة بأكملها، أي أن الحركة يتم تحريكها بشكل متساوٍ طوال الوقت، أو يمكنك تحديد صور متحركة لاستخدام الوقت غير الخطي، مثل استخدام التسريع أو التباطؤ في بداية الحركة أو نهايتها.

تتلقى أدوات الرد الآلي في نظام الصور المتحركة كسرًا من أداة الصور المتحركة يمثّل الوقت المنقضي. تُعدِّل برامج الفاعلية هذا الكسر ليتوافق مع نوع الصور المتحركة التي يهدف إلى تقديمها. يوفّر نظام Android مجموعة من أدوات الاستيفاء الشائعة في android.view.animation package. إذا لم يلائم أيٌّ منها احتياجاتك، يمكنك تنفيذ واجهة TimeInterpolator وإنشاء واجهة خاصة بك.

على سبيل المثال، تتم مقارنة الكسور الواردة أدناه في أداة الاستيفاء التلقائي AccelerateDecelerateInterpolator وLinearInterpolator. ليس لـ LinearInterpolator أي تأثير على الكسر المنقضي. يتسرّع AccelerateDecelerateInterpolator في الحركة ويحدث تباطؤًا خارجها. تحدّد الطرق التالية المنطق الذي تستند إليه هذه الأدوات:

AcccelerateDecelerateIntersolator

Kotlin

override fun getInterpolation(input: Float): Float =
        (Math.cos((input + 1) * Math.PI) / 2.0f).toFloat() + 0.5f

Java

@Override
public float getInterpolation(float input) {
    return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}

المقياس الخطي

Kotlin

override fun getInterpolation(input: Float): Float = input

Java

@Override
public float getInterpolation(float input) {
    return input;
}

يمثّل الجدول التالي القيم التقريبية التي تحتسبها أدوات الاستيفاء هذه لبيانات متحركة تستمر لمدة 1,000 ملي ثانية:

الدقائق المنقضية الكسر المنقضي/الكسر المداخل (خطي) الكسر المضلل (تسريع/تسريع)
0 0 0
200 2. .1
400 4. .345
600 6. 8.
800 8. .9
1,000 1 1

كما يوضِّح الجدول، يغيّر LinearInterpolator القيم بالسرعة نفسها، أي .2 لكل 200 ملي ثانية تمرّ. تعمل قيمة AccelerateDecelerateInterpolator على تغيير القيم بشكلٍ أسرع من LinearInterpolator بين 200 و600 ملي ثانية وأبطأ بين 600 ملي ثانية و1000 ملي ثانية.

تحديد الإطارات الرئيسية

يتكوّن عنصر Keyframe من زوج الوقت/القيمة يتيح لك تحديد حالة معيّنة في وقت محدّد من الصورة المتحركة. ويمكن أن يكون لكل إطار رئيسي أيضًا أداة داخلية خاصة به للتحكم في سلوك الصورة المتحركة خلال الفترة الزمنية بين وقت الإطار الرئيسي السابق ووقت هذا الإطار الرئيسي.

لإنشاء مثيل لكائن Keyframe، يجب استخدام إحدى الطرق الأصلية، ofInt() أو ofFloat() أو ofObject() للحصول على نوع Keyframe المناسب. بعد ذلك، يجب استدعاء الطريقة الأصلية لـ ofKeyframe() للحصول على عنصر PropertyValuesHolder. بعد الحصول على الكائن، يمكنك الحصول على صانع صور متحرّكة من خلال إدخال الكائن PropertyValuesHolder والكائن لتحريكه. ويوضّح مقتطف الرمز التالي كيفية إجراء ذلك:

Kotlin

val kf0 = Keyframe.ofFloat(0f, 0f)
val kf1 = Keyframe.ofFloat(.5f, 360f)
val kf2 = Keyframe.ofFloat(1f, 0f)
val pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2)
ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation).apply {
    duration = 5000
}

Java

Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(.5f, 360f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation);
rotationAnim.setDuration(5000);

صور متحركة

يتيح نظام الصور المتحركة للسمات الصور المتحركة المبسّطة لعناصر العرض، ويقدّم هذا النظام بعض المزايا مقارنةً بنظام الصور المتحركة للعرض. أجرى نظام الصور المتحركة لطريقة العرض تغييرات على عناصر العرض من خلال تغيير طريقة رسمها. وتم التعامل مع هذا الأمر في حاوية كل ملف شخصي، لأنّ الملف الشخصي نفسه لا يحتوي على سمات يمكن معالجتها. وقد أدى ذلك إلى تحريك العرض، ولكن لم ينتج عن ذلك أي تغيير في عنصر العرض نفسه. وأدّى ذلك إلى حدوث سلوك، مثل استمرار ظهور عنصر في موقعه الأصلي على الرغم من رسمه في موقع مختلف على الشاشة. في نظام التشغيل Android 3.0، تمت إضافة خصائص جديدة وطريقة الحصول على البيانات وأساليب الإعداد المقابلة لها لإزالة هذا العيب.

يمكن لنظام الصور المتحركة للخصائص أن يحرّك المشاهدات على الشاشة من خلال تغيير الخصائص الفعلية في عناصر العرض. بالإضافة إلى ذلك، تطلب الملفات الشخصية تلقائيًا طريقة invalidate() لإعادة تحميل الشاشة عند تغيير خصائصها. السمات الجديدة في الفئة View التي تسهّل الصور المتحركة للمواقع هي:

  • translationX وtranslationY: تتحكّم هاتان السمتان في مكان موقع العرض على شكل دلتا من إحداثياته اليمنى والعليا التي تم ضبطها بواسطة حاوية التنسيق.
  • rotation وrotationX وrotationY: تتحكّم هذه السمات في التدوير في الوضع الثنائي الأبعاد (الخاصية rotation) والثلاثي الأبعاد حول النقطة المحورية.
  • scaleX وscaleY: تتحكّم هاتان السمتان في الضبط الثنائي الأبعاد لعرض حول نقطة المحورية.
  • pivotX وpivotY: تتحكّم هاتان السمتان في موقع النقطة المحورية التي تحدث حولها عمليات التدوير والتحجيم. تقع النقطة المحورية في وسط العنصر تلقائيًا.
  • x وy: هما سمتان بسيطتان من الخدمات لوصف الموقع النهائي للعرض في حاويته، كمجموع القيمتين اليمنى والعلوية، وقيم الترجمة X والترجمة Y.
  • alpha: تمثل شفافية ألفا على العرض. تكون هذه القيمة 1 (غير شفافة) تلقائيًا، وتمثّل القيمة 0 الشفافية الكاملة (غير مرئية).

لتحريك خاصية لكائن العرض، مثل اللون أو قيمة الدوران، ما عليك سوى إنشاء مؤثر حركي للخصائص وتحديد سمة العرض التي تريد تحريكها. مثال:

Kotlin

ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f)

Java

ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);

للحصول على مزيد من المعلومات حول إنشاء أدوات الصور المتحركة، يمكنك الاطّلاع على الأقسام المتعلقة بالرسوم المتحركة باستخدام ValueAnimator وObjectAnimator.

إنشاء صور متحرّكة باستخدام ViewPropertyAnimator

توفّر ViewPropertyAnimator طريقة بسيطة لتحريك عدة خصائص View على التوازي باستخدام كائن Animator أساسي واحد. وهي تعمل مثل السمة ObjectAnimator إلى حدّ كبير، لأنّها تعدّل القيم الفعلية لخصائص طريقة العرض، ولكنّها تكون أكثر فعالية عند إضافة تأثيرات حركية إلى العديد من الخصائص في آنٍ واحد. بالإضافة إلى ذلك، يعد رمز استخدام ViewPropertyAnimator أكثر إيجازًا وأسهل في القراءة. تعرِض مقتطفات الرمز التالية الاختلافات في استخدام كائنات ObjectAnimator متعدّدة، وObjectAnimator واحد، وViewPropertyAnimator عند تحريك السمتَين x وy في آن واحد لملف شخصي.

كائنات ObjectAnimator متعددة

Kotlin

val animX = ObjectAnimator.ofFloat(myView, "x", 50f)
val animY = ObjectAnimator.ofFloat(myView, "y", 100f)
AnimatorSet().apply {
    playTogether(animX, animY)
    start()
}

Java

ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);
ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(animX, animY);
animSetXY.start();

أداة One ObjectAnimator

Kotlin

val pvhX = PropertyValuesHolder.ofFloat("x", 50f)
val pvhY = PropertyValuesHolder.ofFloat("y", 100f)
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start()

Java

PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start();

ViewPropertyAnimator

Kotlin

myView.animate().x(50f).y(100f)

Java

myView.animate().x(50f).y(100f);

للحصول على معلومات أكثر تفصيلاً حول ViewPropertyAnimator، يمكنك الاطّلاع على مشاركة المدونة المعنيّة بمطوّري تطبيقات Android.

تعريف الصور المتحركة في XML

يتيح لك نظام الصور المتحركة للسمات الإعلان عن الصور المتحركة للسمات باستخدام تنسيق XML بدلاً من استخدامها آليًا. من خلال تحديد الصور المتحركة في ملف XML، يمكنك إعادة استخدامها بسهولة في أنشطة متعددة وتعديل تسلسل الصور المتحركة بسهولة أكبر.

للتمييز بين ملفات الصور المتحركة التي تستخدم واجهات برمجة التطبيقات للصور المتحركة الجديدة وتلك التي تستخدم إطار العمل القديم للعرض المتحركة، بدءًا من الإصدار 3.1 من Android، عليك حفظ ملفات XML للصور المتحركة الجديدة في دليل res/animator/.

تتوافق فئات الصور المتحركة التالية في المواقع الإلكترونية مع تعريف XML مع علامات XML التالية:

للعثور على السمات التي يمكنك استخدامها في بيان XML، يُرجى الاطّلاع على موارد الصور المتحركة. في المثال التالي، يتم تشغيل مجموعتي الرسوم المتحركة للكائنات بالتتابع، مع تشغيل أول مجموعة مدمجة لاثنتين من الرسوم المتحركة للكائنات معًا:

<set android:ordering="sequentially">
    <set>
        <objectAnimator
            android:propertyName="x"
            android:duration="500"
            android:valueTo="400"
            android:valueType="intType"/>
        <objectAnimator
            android:propertyName="y"
            android:duration="500"
            android:valueTo="300"
            android:valueType="intType"/>
    </set>
    <objectAnimator
        android:propertyName="alpha"
        android:duration="500"
        android:valueTo="1f"/>
</set>

لتشغيل هذه الحركة، عليك تضخيم موارد XML في الرمز إلى كائن AnimatorSet، ثم ضبط الكائنات المستهدفة لكل الصور المتحركة قبل بدء مجموعة الصور المتحركة. يؤدي استدعاء setTarget() إلى ضبط كائن هدف واحد لجميع عناصر AnimatorSet الثانوية لتسهيل الأمر. ويوضِّح الرمز البرمجي التالي كيفية إجراء ذلك:

Kotlin

(AnimatorInflater.loadAnimator(myContext, R.animator.property_animator) as AnimatorSet).apply {
    setTarget(myObject)
    start()
}

Java

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
    R.animator.property_animator);
set.setTarget(myObject);
set.start();

يمكنك أيضًا الإعلان عن ValueAnimator بتنسيق XML، كما هو موضّح في المثال التالي:

<animator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:valueType="floatType"
    android:valueFrom="0f"
    android:valueTo="-100f" />

لاستخدام ValueAnimator السابقة في الرمز الخاص بك، عليك تضخيم العنصر وإضافة AnimatorUpdateListener والحصول على قيمة الحركة المعدَّلة واستخدامها في سمة لأحد طرق العرض، كما هو موضّح في الرمز التالي:

Kotlin

(AnimatorInflater.loadAnimator(this, R.animator.animator) as ValueAnimator).apply {
    addUpdateListener { updatedAnimation ->
        textView.translationX = updatedAnimation.animatedValue as Float
    }

    start()
}

Java

ValueAnimator xmlAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this,
        R.animator.animator);
xmlAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator updatedAnimation) {
        float animatedValue = (float)updatedAnimation.getAnimatedValue();
        textView.setTranslationX(animatedValue);
    }
});

xmlAnimator.start();

للحصول على معلومات عن بنية XML لتحديد الصور المتحركة للخصائص، يمكنك الاطّلاع على موارد الصور المتحركة .

التأثيرات المحتملة على أداء واجهة المستخدم

تتسبب عوامل الرسوم المتحركة التي تقوم بتحديث واجهة المستخدم في إحداث عمل عرض إضافي لكل إطار يتم تشغيل الرسوم المتحركة فيه. لهذا السبب، يمكن أن يؤثر استخدام الرسوم المتحركة التي تستهلك قدرًا كبيرًا من الموارد سلبًا على أداء تطبيقك.

تتم إضافة العمل المطلوب لتحريك واجهة المستخدم إلى مرحلة الرسوم المتحركة في مسار العرض. يمكنك معرفة ما إذا كانت الرسوم المتحركة تؤثر في أداء تطبيقك أم لا من خلال تفعيل عرض وحدة معالجة الرسومات الملف الشخصي ومراقبة مرحلة الصور المتحركة. لمزيد من المعلومات، يُرجى الاطّلاع على جولة تفصيلية حول عرض وحدة معالجة الرسومات الملف الشخصي.