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

تجربة طريقة ComposeAllowed
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 .تقريبًا، أقل من الكسر المنقضي، وهو .25، عند t = 10 ملي ثانية. في الشكل 1، يكون الكسر المُدرج دائمًا مماثلاً للكسر المنقضي.

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

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

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

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

من خلال نظام الصور المتحركة للسمات، تتم إزالة هذه القيود بالكامل، ويمكنك تحريك أي سمة لأي كائن (Views وnot-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 وقيم اللون أيضًا، إذا كنت تريد معالجة هذه الأنواع على نحو مختلف عن السلوك التلقائي. راجِع القسم المتعلق بـ استخدام مقيّم TypeEvaluator لمزيد من المعلومات حول طريقة كتابة مقيّم مخصّص.

تحدّد أداة تعديل الوقت طريقة احتساب القيم الخاصة في الصورة المتحركة كدالة وقت. على سبيل المثال، يمكنك تحديد الصور المتحركة ليتم عرضها بشكل خطي على شكل الحركة بأكملها، ما يعني أنّ الحركة تتحرك بشكل متساوٍ طوال الوقت، أو يمكنك تحديد الصور المتحركة لاستخدام وقت غير خطي، مثل التسريع في بداية الصورة المتحركة وخفضها في نهايتها. يصف الجدول 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، لديك ثلاثة خيارات:
    • أضف طريقة setter إلى الفئة إذا كنت تملك الحق في ذلك.
    • استخدِم فئة برنامج تضمين لديك حقوق تغييرها، واحرص على أن يتلقّى برنامج تضمين القيمة القيمة باستخدام طريقة 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 الانتقال إلى صورة متحركة تظهر وتختفي عند إضافتها إلى ViewGroup أو إزالتها منه أو عند استدعاء طريقة setVisibility() View باستخدام 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" />

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

تحريك تغييرات حالة العرض باستخدام 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>

استخدام أداة TypeEvaluator

إذا أردت إضافة تأثير متحرك إلى نوع غير معروف في نظام 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 إلى الصورة المتحركة ويتباطأ خارجه. تحدّد الطرق التالية منطق أدوات الاستيفاء هذه:

AccelerateDecelerateInterpolator

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 و1,000 ملي ثانية.

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

يتكوّن عنصر 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 وTranslationY.
  • alpha: يمثل شفافية ألفا في العرض. تكون هذه القيمة 1 (معتمة) بشكل تلقائي، وتمثل القيمة 0 الشفافية الكاملة (غير مرئية).

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

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 في الوقت نفسه من أي ملف شخصي.

كائنات عناصر متحركة متعددة

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، يمكنك بسهولة إعادة استخدام الصور المتحركة في أنشطة متعددة وتعديل تسلسل الصور بسهولة أكبر.

للتفريق بين ملفات الصور المتحركة التي تستخدم واجهات برمجة التطبيقات الجديدة للصور المتحركة للخصائص وتلك التي تستخدم إطار عمل الصور المتحركة القديم، بدءًا من الإصدار Android 3.1، عليك حفظ ملفات 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 لتحديد الصور المتحركة للسمات، يمكنك الاطّلاع على موارد الصور المتحركة .

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

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

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