نظام الصور المتحركة للخصائص هو إطار عمل قوي يتيح لك تحريك أي عنصر تقريبًا. يمكنك تحديد حركة لتغيير أي خاصية من خصائص الكائن بمرور الوقت، بغض النظر عمّا إذا كان يتم عرضه على الشاشة أم لا. تغيّر حركة السمة قيمة السمة (حقل في عنصر) على مدار فترة زمنية محددة. لتحريك عنصر، عليك تحديد سمة العنصر التي تريد تحريكها، مثل موضع العنصر على الشاشة، ومدة التحريك، والقيم التي تريد التحريك بينها.
يتيح لك نظام الرسوم المتحركة للسمات تحديد الخصائص التالية للرسوم المتحركة:
- المدة: يمكنك تحديد مدة الحركة. الطول التلقائي هو 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 مللي ثانية هو 0 .25
لأنّ المدة الإجمالية هي t = 40 مللي ثانية.
عندما ينتهي ValueAnimator من حساب جزء من الوقت المنقضي، يستدعي TimeInterpolator المضبوط حاليًا لحساب جزء من الوقت المنقضي معدَّل. تعيِّن قيمة كسرية معدَّلة القيمة الكسرية المنقضية إلى قيمة كسرية جديدة تأخذ في الاعتبار عملية تعديل الوقت التي تم ضبطها. على سبيل المثال، في الشكل 2، بما أنّ الحركة تتسارع ببطء، يكون الجزء المحسوب، أي 0 .15 تقريبًا، أقل من الجزء المنقضي، أي 0.25، عند t = 10 مللي ثانية. في الشكل 1، يكون الجزء المحسوب دائمًا هو نفسه الجزء المنقضي.
عند احتساب الجزء المحدّد، تستدعي ValueAnimator
TypeEvaluator المناسبة لاحتساب قيمة السمة التي يتم تحريكها، استنادًا إلى الجزء المحدّد وقيمة البدء وقيمة
النهاية للرسم المتحرك. على سبيل المثال، في الشكل 2، كان الكسر المستوفى هو 0 .15 عند t = 10 ملي ثانية، وبالتالي ستكون قيمة السمة في ذلك الوقت هي 0 .15 × (40 - 0)، أي 6.
كيف تختلف الرسوم المتحركة للخصائص عن الرسوم المتحركة للعرض
يتيح نظام عرض الصور المتحركة إمكانية تحريك عناصر View فقط، لذا إذا أردت تحريك عناصر غير View، عليك تنفيذ الرمز الخاص بك لإجراء ذلك. ويقتصر نظام عرض الصور المتحركة أيضًا على عرض بعض جوانب عنصر View فقط لتحريكها، مثل تغيير حجم العرض وتدويره، ولكن ليس لون الخلفية مثلاً.
من عيوب نظام الرسوم المتحركة للعرض أنّه كان يعدّل فقط موضع رسم العرض، وليس العرض نفسه. على سبيل المثال، إذا حرّكت زرًا على الشاشة، سيتم رسم الزر بشكل صحيح، ولكن لن يتغيّر الموقع الفعلي الذي يمكنك النقر عليه، لذا عليك تنفيذ منطقك الخاص للتعامل مع هذا الأمر.
باستخدام نظام الصور المتحركة للعناصر، تتم إزالة هذه القيود تمامًا، ويمكنك إنشاء صور متحركة لأي عنصر (عناصر مرئية وغير مرئية) وتعديل العنصر نفسه. ويتميّز نظام الرسوم المتحركة للسمات أيضًا بفعالية أكبر في تنفيذ الرسوم المتحركة. على مستوى عالٍ، يمكنك تعيين أدوات إنشاء رسوم متحركة للخصائص التي تريد تحريكها، مثل اللون أو الموضع أو الحجم، ويمكنك تحديد جوانب الحركة، مثل الاستيفاء والمزامنة بين أدوات إنشاء رسوم متحركة متعددة.
في المقابل، يستغرق نظام تحريك العرض وقتًا أقل في الإعداد ويتطلّب كتابة رموز برمجية أقل. إذا كانت الرسوم المتحركة للعرض تنجز كل ما تحتاج إليه، أو إذا كان الرمز الحالي يعمل بالطريقة التي تريدها، فلا داعي لاستخدام نظام الرسوم المتحركة للخاصية. وقد يكون من المنطقي أيضًا استخدام نظامَي الرسوم المتحركة معًا في مواقف مختلفة إذا دعت الحاجة إلى ذلك.
نظرة عامة على واجهة برمجة التطبيقات
يمكنك العثور على معظم واجهات برمجة التطبيقات لنظام تحريك العناصر في android.animation. بما أنّ نظام عرض الرسوم المتحركة يحدّد العديد من أدوات الاستيفاء في android.view.animation، يمكنك استخدام أدوات الاستيفاء هذه في نظام الرسوم المتحركة للسمات أيضًا. توضّح الجداول التالية المكوّنات الرئيسية لنظام حركة العناصر.
يوفر الصف Animator البنية الأساسية لإنشاء الصور المتحركة. لا تستخدم هذه الفئة عادةً بشكل مباشر لأنّها توفّر وظائف بسيطة فقط يجب توسيعها لتتيح إمكانية تحريك القيم بالكامل. توسّع الفئات الفرعية التالية الفئة Animator:
الجدول 1. أداة صناعة الصورة المتحركة
| الفئة | الوصف |
|---|---|
ValueAnimator |
محرك التوقيت الرئيسي لرسوم متحركة خاصة بالخصائص، والذي يحتسب أيضًا قيم الخصائص التي سيتم تحريكها. تتضمّن هذه الفئة جميع الوظائف الأساسية التي تحتسب قيم الصور المتحركة، كما تتضمّن تفاصيل التوقيت لكل صورة متحركة، ومعلومات حول ما إذا كانت الصورة المتحركة تتكرّر، وبرامج معالجة الأحداث التي تتلقّى أحداث التعديل، وإمكانية ضبط أنواع مخصّصة لتقييمها. هناك جزآن لتحريك الخصائص: احتساب القيم المتحركة
وتعيين هذه القيم على العنصر والخاصية اللذين يتم تحريكهما. لا تنفّذ ValueAnimator الجزء الثاني، لذا عليك الاستماع إلى التعديلات على القيم التي تحتسبها ValueAnimator وتعديل الكائنات التي تريد تحريكها باستخدام المنطق الخاص بك. راجِع القسم حول
إنشاء رسوم متحركة باستخدام ValueAnimator للحصول على مزيد من المعلومات. |
ObjectAnimator |
فئة فرعية من ValueAnimator تتيح لك ضبط عنصر مستهدف وسمة عنصر لتحريكه. تعدّل هذه الفئة السمة وفقًا لذلك عند احتساب قيمة جديدة للحركة. ننصحك باستخدام
ObjectAnimator في معظم الأحيان،
لأنّها تسهّل عملية تحريك القيم على العناصر المستهدَفة. ومع ذلك، قد تحتاج أحيانًا إلى استخدام ValueAnimator مباشرةً لأنّ ObjectAnimator يتضمّن بعض القيود الإضافية، مثل اشتراط توفّر طرق وصول محدّدة في العنصر المستهدف. |
AnimatorSet |
توفّر هذه السمة آلية لتجميع الرسوم المتحركة معًا كي يتم تشغيلها بالنسبة إلى بعضها البعض. يمكنك ضبط الرسوم المتحركة ليتم تشغيلها معًا أو بالتسلسل أو بعد تأخير محدّد. راجِع القسم حول تصميم حركات متعدّدة باستخدام مجموعات Animator للحصول على مزيد من المعلومات. |
تخبر أدوات التقييم نظام حركة العناصر كيف يتم احتساب قيم سمة معيّنة. تستند هذه الدوال إلى بيانات التوقيت التي توفّرها الفئة 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، لمدة 1000 ملي ثانية، عند تشغيل الطريقة 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 لمدة 1000 ملي ثانية، وذلك عند تنفيذ الطريقة 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 (بصيغة camel case) بالشكل
set<PropertyName>(). بما أنّObjectAnimatorتعدّل الموقع تلقائيًا أثناء الحركة، يجب أن تتمكّن من الوصول إلى الموقع باستخدام طريقة الضبط هذه. على سبيل المثال، إذا كان اسم السمةfoo، يجب أن يتوفّر لديك الإجراءsetFoo(). إذا لم تكن طريقة الضبط هذه متوفّرة، لديك ثلاثة خيارات:- أضِف طريقة الضبط إلى الفئة إذا كان لديك الحق في إجراء ذلك.
- استخدِم فئة التفاف لديك حقوق تغييرها، واجعل هذه الفئة تتلقّى القيمة باستخدام طريقة ضبط صالحة، ثم أرسِلها إلى العنصر الأصلي.
- يمكن استخدام
ValueAnimatorكبديل.
- إذا حدّدت قيمة واحدة فقط للمَعلمة
values...في إحدى طرق المصنعObjectAnimator، سيتم افتراض أنّها القيمة النهائية للحركة. لذلك، يجب أن تتضمّن سمة العنصر التي يتم تحريكها دالة getter تُستخدَم للحصول على القيمة الأولية للحركة. يجب أن تكون دالة إرجاع القيمة بالتنسيقget<PropertyName>(). على سبيل المثال، إذا كان اسم السمةfoo، يجب أن يتوفّر الإجراءgetFoo(). - يجب أن تعمل طريقتَا إرجاع القيمة (إذا لزم الأمر) وتحديد القيمة للسمة التي تحرّكها على النوع نفسه من قيمتَي البدء والانتهاء اللتين تحدّدهما في
ObjectAnimator. على سبيل المثال، يجب أن يتوفّر لديكtargetObject.setPropName(float)وtargetObject.getPropName()إذا أنشأتObjectAnimatorالتالية:ObjectAnimator.ofFloat(targetObject, "propName", 1f)
- اعتمادًا على السمة أو العنصر الذي تريد تحريكه، قد تحتاج إلى استدعاء الطريقة
invalidate()في View لإجبار الشاشة على إعادة رسم نفسها باستخدام القيم المتحركة المعدَّلة. يتم ذلك فيonAnimationUpdate()الدالة التي يتم استدعاؤها. على سبيل المثال، لا يؤدي تحريك سمة اللون لكائن Drawable إلى تعديل الشاشة إلا عندما يعيد هذا الكائن رسم نفسه. تؤدي جميع أدوات ضبط الموقع في View، مثلsetAlpha()وsetTranslationX()، إلى إبطال View بشكل صحيح، لذا لا تحتاج إلى إبطال View عند استدعاء هذه الطرق بقِيَم جديدة. لمزيد من المعلومات حول أدوات الاستماع، راجِع القسم حول أدوات الاستماع إلى الصور المتحركة.
تصميم عدة رسوم متحركة باستخدام AnimatorSet
في كثير من الحالات، تريد تشغيل صورة متحركة تعتمد على وقت بدء صورة متحركة أخرى أو انتهائها. يتيح لك نظام Android تجميع الصور المتحركة معًا في AnimatorSet، ما يتيح لك تحديد ما إذا كنت تريد بدء الصور المتحركة في وقت واحد أو بالتسلسل أو بعد تأخير محدّد. يمكنك أيضًا تضمين عناصر AnimatorSet داخل بعضها البعض.
يشغّل مقتطف الرمز التالي عناصر Animator
بالطريقة التالية:
- تشغيل
bounceAnim - تشغيل
squashAnim1وsquashAnim2وstretchAnim1وstretchAnim2في الوقت نفسه - تشغيل
bounceBackAnim - تشغيل
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.AnimatorListeneronAnimationStart()- يتم استدعاؤها عند بدء الحركة.onAnimationEnd()- يتم استدعاؤها عند انتهاء الحركة.-
onAnimationRepeat(): يتم استدعاؤه عندما تتكرر الحركة. -
onAnimationCancel(): يتم استدعاؤها عند إلغاء الصورة المتحركة. يتم أيضًا استدعاءonAnimationEnd()عند إلغاء صورة متحركة، بغض النظر عن طريقة إنهاء الصورة.
ValueAnimator.AnimatorUpdateListener-
onAnimationUpdate(): يتم استدعاؤها في كل إطار من الصورة المتحركة. استمع إلى هذا الحدث لاستخدام القيم المحسوبة التي تم إنشاؤها بواسطةValueAnimatorأثناء عرض رسم متحرك. لاستخدام القيمة، يمكنك طلب العنصرValueAnimatorالذي تم تمريره إلى الحدث للحصول على القيمة المتحركة الحالية باستخدام الطريقةgetAnimatedValue(). يجب تنفيذ أداة معالجة الأحداث هذه في حال استخدامValueAnimator.استنادًا إلى الموقع أو العنصر الذي تحرّكه، قد تحتاج إلى استدعاء
invalidate()على View لإعادة رسم هذا الجزء من الشاشة باستخدام القيم المتحركة الجديدة. على سبيل المثال، لن يؤدي تحريك سمة اللون الخاصة بكائن Drawable إلى تعديل الشاشة إلا عندما يعيد الكائن رسم نفسه. تؤدي جميع أدوات ضبط الموقع على View، مثلsetAlpha()وsetTranslationX()، إلى إبطال View بشكل صحيح، لذا لا تحتاج إلى إبطال View عند استدعاء هذه الطرق بقيم جديدة.
-
يمكنك توسيع فئة 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; }
LinearInterpolator
Kotlin
override fun getInterpolation(input: Float): Float = input
Java
@Override public float getInterpolation(float input) { return input; }
يمثّل الجدول التالي القيم التقريبية التي يتم احتسابها بواسطة أدوات الاستيفاء هذه للرسوم المتحركة التي تستغرق 1000 ملي ثانية:
| المدة المنقضية بالملي ثانية | الكسر المنقضي/الكسر المستوفى (خطي) | الكسر المُستكمَل (تسريع/إبطاء) |
|---|---|---|
| 0 | 0 | 0 |
| 200 | .2 | .1 |
| 400 | .4 | .345 |
| 600 | .6 | .654 |
| 800 | .8 | .9 |
| 1000 | 1 | 1 |
كما يوضّح الجدول، يغيّر LinearInterpolator القيم
بالسرعة نفسها، أي 0.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);
تحريك طرق العرض
يتيح نظام الصور المتحركة للخصائص إنشاء صور متحركة مبسطة لعناصر View، كما يوفّر بعض المزايا مقارنةً بنظام الصور المتحركة للعناصر. حوّل نظام الرسوم المتحركة للعرض كائنات العرض من خلال تغيير طريقة رسمها. تم التعامل مع ذلك في حاوية كل طريقة عرض، لأنّ طريقة العرض نفسها لم تتضمّن أي سمات يمكن التلاعب بها. أدّى ذلك إلى تحريك العرض، ولكن لم يحدث أي تغيير في عنصر العرض نفسه. وقد أدّى ذلك إلى سلوكيات مثل بقاء عنصر في موقعه الأصلي، حتى لو تم رسمه في موقع مختلف على الشاشة. في الإصدار 3.0 من نظام التشغيل Android، تمت إضافة خصائص جديدة وطُرق getter وsetter المقابلة للتخلص من هذا العيب.
يمكن لنظام الصور المتحركة للخصائص تحريك "طرق العرض" على الشاشة من خلال تغيير الخصائص الفعلية في عناصر "طريقة العرض". بالإضافة إلى ذلك، تستدعي طرق العرض تلقائيًا الطريقة invalidate() لإعادة تحميل الشاشة كلما تم تغيير خصائصها. السمات الجديدة في الفئة View التي تسهّل إنشاء صور متحركة للسمات هي:
-
translationXوtranslationY: تتحكّم هاتان السمتان في موضع العرض كقيمة دلتا من الإحداثيات اليسرى والعلوية التي يحدّدها حاوية التنسيق. -
rotationوrotationXوrotationY: تتحكّم هذه السمات في التدوير في وضعَي العرض الثنائي الأبعاد (السمةrotation) والثلاثي الأبعاد حول نقطة الارتكاز. -
scaleXوscaleY: تتحكّم هاتان السمتان في تغيير حجم العرض الثنائي الأبعاد حول نقطة الارتكاز. pivotXوpivotY: تتحكّم هاتان السمتان في موضع نقطة الارتكاز التي تحدث حولها عمليات الدوران وتغيير الحجم. يقع محور الارتكاز تلقائيًا في منتصف العنصر.-
xوy: هما سمتان بسيطتان للأدوات المساعدة لوصف الموقع النهائي للعنصر View في الحاوية، وذلك كمجموع لقيمتَي left وtop وقيمتَي translationX وtranslationY. alpha: تمثّل هذه السمة مستوى الشفافية في العرض. القيمة التلقائية هي 1 (معتم)، والقيمة 0 تشير إلى الشفافية الكاملة (غير مرئي).
لتحريك إحدى سمات عنصر View، مثل لونه أو قيمة دورانه، ما عليك سوى إنشاء أداة تحريك للسمات وتحديد سمة 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 لإحدى طرق العرض في الوقت نفسه.
عناصر 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، يمكنك إعادة استخدامها بسهولة في أنشطة متعددة وتعديل تسلسل الرسوم المتحركة بسهولة أكبر.
للتمييز بين ملفات الصور المتحركة التي تستخدم واجهات برمجة التطبيقات الجديدة للصور المتحركة التي تستخدم الخصائص وتلك التي تستخدم إطار عمل الصور المتحركة القديم، يجب حفظ ملفات XML الخاصة بالصور المتحركة التي تستخدم الخصائص في الدليل res/animator/ بدءًا من الإصدار 3.1 من نظام التشغيل Android.
تتيح فئات الرسوم المتحركة التالية للسمات إمكانية تعريفها في ملف XML باستخدام علامات XML التالية:
ValueAnimator-<animator>ObjectAnimator-<objectAnimator>AnimatorSet-<set>
للعثور على السمات التي يمكنك استخدامها في تعريف 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 لتحديد حركات العناصر، اطّلِع على موارد الحركات .
التأثيرات المحتملة على أداء واجهة المستخدِم
تتسبّب أدوات إنشاء الصور المتحركة التي تعدّل واجهة المستخدم في تنفيذ عمل إضافي لعرض كل إطار يتم فيه تشغيل الصورة المتحركة. لهذا السبب، يمكن أن يؤثر استخدام الرسوم المتحركة التي تستهلك الكثير من الموارد سلبًا في أداء تطبيقك.
تتم إضافة العمل المطلوب لتحريك واجهة المستخدم إلى مرحلة الرسوم المتحركة في مسار العرض. يمكنك معرفة ما إذا كانت الرسوم المتحركة تؤثر في أداء تطبيقك من خلال تفعيل خيار رسم مخطط لعرض GPU ومراقبة مرحلة الرسوم المتحركة. لمزيد من المعلومات، راجِع شرح ميزة "رسم مخطط لعرض GPU".