סקירה כללית של אנימציה של נכס

רוצה לנסות את שיטת הכתיבה?
'Jetpack פיתוח נייטיב' היא ערכת הכלים המומלצת לממשק המשתמש ל-Android. איך משתמשים באנימציות במצב 'כתיבה'

מערכת האנימציה של המאפיינים היא מסגרת אפקטיבית שמאפשרת כדי להנפיש כמעט כל דבר. אפשר להגדיר אנימציה כדי לשנות כל מאפיין אובייקט לאורך זמן, בין אם הוא קשור למסך או לא. אנימציה של נכס משנה נכס (שדה באובייקט) לאורך פרק זמן שצוין. כדי להוסיף אנימציה לפריט כלשהו, צריך לציין מאפיין האובייקט שרוצים להוסיף לו אנימציה, כמו מיקום האובייקט במסך, משך הזמן שתרצו ליצור לו אנימציה, ואילו ערכים תרצו להנפיש.

מערכת האנימציה של המאפיינים מאפשרת להגדיר את המאפיינים הבאים של אנימציה:

  • משך זמן: אפשר להגדיר את משך האנימציה. אורך ברירת המחדל הוא 300 אלפיות השנייה.
  • אינטרפולציה של זמן: אפשר לציין איך ערכי הנכס מחושבים הפונקציה של הזמן שחלף עכשיו באנימציה.
  • ספירה והתנהגות של אנימציה: ניתן לציין אם אנימציה תחזור על עצמה מגיע לסוף משך הזמן של האנימציה וכמה פעמים לחזור על אותה אנימציה. אפשר גם לציין אם רוצים שהאנימציה תופעל בסדר הפוך. המערכת מגדירה אותו כדי להפוך הפעלות את האנימציה קדימה ואז אחורה שוב ושוב, עד שמגיעים למספר החזרות.
  • ערכות של אנימטורים: אפשר לקבץ אנימציות לערכות לוגיות שפועלות יחד או ברצף או לאחר עיכובים מסוימים.
  • השהיה ברענון פריימים: אפשר לציין באיזו תדירות לרענן את הפריימים באנימציה. ברירת המחדל מוגדרת לרענון כל 10 אלפיות השנייה, אבל המהירות שבה האפליקציה יכולה לרענן פריימים היא תלוי בסופו של דבר במידת העומס הכוללת של המערכת ובמהירות שבה המערכת יכולה לטפל בטיימר הבסיסי.

כדי לראות דוגמה מלאה לאנימציה של נכס, אפשר לעיין ב כיתה אחת (ChangeColor) בהתאמה אישית לדוגמה ב-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 אלפיות השנייה, ולכן ערך הנכס באותו זמן יהיה 0 .15 × (40 - 0) או 6.

מה ההבדל בין האנימציה של נכס לבין האנימציה של התצוגה המפורטת

מערכת האנימציה של התצוגה מאפשרת להוסיף אנימציה רק ל-View ולכן אם רציתם ליצור אנימציה לאובייקטים שאינם View, צריך להטמיע כדי לעשות את זה, גם מערכת האנימציה של הצפיות מוגבלת, כי היא רק חושף כמה היבטים של אובייקט View להנפשה, כמו התאמה לעומס (scaling) סיבוב של תצוגה, אבל לא של צבע הרקע.

חיסרון נוסף של מערכת האנימציה של התצוגה הוא שהיא שונתה רק כאשר התצוגה שורטטה, ולא התצוגה עצמה. לדוגמה, אם יצרתם אנימציה של לחצן כדי להזיז על המסך, הלחצן משורטט בצורה נכונה, אך המיקום בפועל שבו ניתן ללחוץ על לא משתנה, לכן עליכם להטמיע לוגיקה משלכם כדי לטפל בכך.

באמצעות מערכת האנימציה של המאפיינים, המגבלות האלה מוסרות לחלוטין ואפשר להוסיף אנימציה כל מאפיין של אובייקט כלשהו (Views ולא תצוגות) והאובייקט עצמו משתנה בפועל. מערכת האנימציה של המאפיין גם עוצמתית יותר באופן שבו היא מבצעת אנימציה. בשעה למשל, מקצים אנימטורים למאפיינים שרוצים להנפיש, כמו צבעים, המיקום או הגודל שלו, והם יכולים להגדיר היבטים של האנימציה, כמו אינטרפולציה סנכרון של מספר אנימטורים.

עם זאת, תהליך ההגדרה של מערכת האנימציה של התצוגה נמשך פחות זמן ונדרש פחות זמן בכתיבה. אם אנימציית התצוגה משיגה את כל מה שצריך לעשות, או אם הקוד הקיים כבר עובד. פועל באופן הרצוי, אין צורך להשתמש במערכת האנימציה של המאפיינים. ייתכן גם הגיוני להשתמש בשתי מערכות האנימציה במצבים שונים, אם התרחיש לדוגמה הזה נובע מכך.

סקירה כללית על ממשקי API

רוב ממשקי ה-API של מערכת האנימציה של הנכסים זמינים ב-android.animation. כי מערכת הצגת האנימציה כבר שמגדיר הרבה אינטרפולטורים ב-android.view.animation, אפשר להשתמש האינטרפולטורים האלו גם במערכת האנימציה של הנכס. בטבלאות הבאות מתואר בעיקר רכיבים של מערכת האנימציה של המאפיינים.

המחלקה Animator מספקת את המבנה הבסיסי ליצירה אנימציות. בדרך כלל לא משתמשים בכיתה הזו ישירות, כי היא מספקת פונקציונליות שצריך להרחיב כדי לתמוך באופן מלא בערכים מונפשים. הבאים כיתות המשנה מתרחבות ב-Animator:

טבלה 1. אנימטורים

דרגה תיאור
ValueAnimator מנוע התזמון הראשי לאנימציה של הנכס, שמחשב גם את הערכים של להנפשה. יש לו את כל הפונקציונליות העיקרית שמחשבת את האנימציה ומכיל את פרטי התזמון של כל אנימציה, מידע שמציין אם אנימציות חוזרות, מאזינים שמקבלים אירועי עדכון ואפשרות להגדיר פקודות מותאמות אישית כדי להעריך אותם. קיימים שני חלקים במאפיינים של אנימציה: חישוב של תוכן אנימציה והגדרת הערכים האלה באובייקט ובמאפיין שמונפשים. החלק השני לא נשמר ב-ValueAnimator, לכן עליך להאזין לעדכונים בערכים המחושבים לפי ValueAnimator ו- לשנות את האובייקטים שאותם אתם רוצים להוסיף לאנימציה בעזרת הלוגיקה שלכם. מעבר לקטע על הוספת אנימציה עם ValueAnimator כדי לקבל מידע נוסף.
ObjectAnimator תת-מחלקה של ValueAnimator שמאפשרת להגדיר יעד של אובייקט ואובייקט להנפשה. הכיתה מעדכנת את הנכס בהתאם כאשר ומחשב ערך חדש עבור האנימציה. אתם רוצים להשתמש ObjectAnimator ברוב המקרים, כי הוא הופך את התהליך של הוספת אנימציה לערכים של אובייקטי יעד, הרבה יותר קל. אבל, לפעמים לפעמים רוצים להשתמש ישירות באפליקציה ValueAnimator, כי ב-ObjectAnimator יש עוד כמה הגבלות, כמו דרישה methods של רכיב גישה שיהיו באובייקט היעד.
AnimatorSet מספקת מנגנון לקיבוץ אנימציות יחד כדי שיפעלו יחסים ביניהן. אפשר להגדיר את האנימציות שיופעלו ביחד, ברצף או אחריו עיכוב מוגדר. ניתן לעיין בקטע בנושא כוריאוגרפיה של מספר מודעות אנימציות עם ערכות אנימטור כדי לקבל מידע נוסף.

מעריכים אומרים למערכת האנימציה של המאפיינים איך לחשב את הערכים של מימד נתון לנכס. הן לוקחות את נתוני התזמון שסופקו על ידי Animator class, את ערך ההתחלה והסיום של האנימציה, ומחשב את הערכים המונפשים של המאפיין על סמך הנתונים האלה. מערכת האנימציה של המאפיינים מספקת את הבודקים הבאים:

טבלה 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 מעדכן באופן אוטומטי את המאפיין במהלך האנימציה, חייבת להיות לו גישה לנכס באמצעות ה-method הזה. לדוגמה, אם שם הנכס הוא foo, צריך יש שיטת setFoo(). אם ה-method הזה לא קיים, יש לכם אפשרויות:
    • אם יש לכם זכויות לעשות זאת, עליכם להוסיף לכיתה את שיטת ההגדרה.
    • משתמשים במחלקה של wrapper שיש לכם זכויות לשנות וה-wrapper הזה יקבל את עם שיטת מגדיר חוקית ומעבירים אותו לאובייקט המקורי.
    • במקומה צריך להשתמש במדיניות ValueAnimator.
  • אם מציינים רק ערך אחד לפרמטר values... באחת מהשיטות של היצרן ל-ObjectAnimator, ההנחה היא שהוא ערך הסיום של אנימציה. לכן, למאפיין האובייקט שאתם יוצרים אנימציה חייבת להיות פונקציית getter שמשמש לקבלת ערך ההתחלה של האנימציה. הפונקציה getter חייבת להיות בקטע של get<PropertyName>(). לדוגמה, אם שם הנכס הוא foo, צריכה להיות לך method getFoo().
  • השיטות של getter (במידת הצורך) והשיטה הזו של הנכס שמונפשות חייבות פועלים על אותו סוג כמו ערכי ההתחלה והסיום שציינתם ל-ObjectAnimator. לדוגמה, אתם צריכים targetObject.setPropName(float) ו-targetObject.getPropName() אם יוצרים את ה-ObjectAnimator הבא:
    ObjectAnimator.ofFloat(targetObject, "propName", 1f)
    
  • בהתאם למאפיין או לאובייקט שאתם יוצרים באנימציה, ייתכן שתצטרכו לקרוא ל-method 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(). ההטמעה של המדיניות הזו חובה להשתמש ב-listener אם משתמשים ב-ValueAnimator.

      בהתאם לנכס או לאובייקט שאתם יוצרים באנימציה, ייתכן שתצטרכו להפעיל invalidate() בתצוגה כדי לאלץ את האזור הזה כדי לצייר מחדש על עצמו את הערכים המונפשים החדשים. לדוגמה, הנפשה של מאפיין צבע של אובייקט ניתן להזזה גורם לעדכונים במסך רק כאשר האובייקט הזה מצייר את עצמו מחדש. כל מאפייני הנכסים ב-View, כמו 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()) עם 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" />

אם מגדירים את המאפיין הזה כ-True, מתבצעת באופן אוטומטי אנימציה של תצוגות שנוספות או הוסרו גם ViewGroup וגם את התצוגות המפורטות האחרות ב-ViewGroup.

הנפשה של שינויים במצב התצוגה באמצעות StateListAnimator

המחלקה StateListAnimator מאפשרת להגדיר אנימטורים שפועלים כאשר המצב של צפייה משתנה. האובייקט הזה פועל כ-wrapper אובייקט 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.
1000 1 1

כפי שמוצג בטבלה, השדה LinearInterpolator משנה את הערכים באותה מהירות, 0.2 לכל 200 אלפיות השנייה שחולפות. AccelerateDecelerateInterpolator משנה את הערכים מהר יותר מ-LinearInterpolator בין 200 אלפיות השנייה ל-600 אלפיות השנייה, ולאט יותר בין 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);

אנימציית צפיות

מערכת האנימציה של המאפיינים מאפשרת אנימציה יעילה של הצגת אובייקטים ומבצעים יש כמה יתרונות על פני מערכת האנימציה של התצוגה. התצוגה מערכת האנימציה ביצעה טרנספורמציה של הצגת האובייקטים על ידי שינוי הדרך שבה הם צוירו. זה היה מטופל בתוך המאגר של כל תצוגה מפורטת, מפני שלתצוגה המפורטת עצמה לא היו מאפיינים שניתן לשנות. כתוצאה מכך, התצוגה הונפשה, אך לא גרמה לשינוי באובייקט ה-View עצמו. הזה שהובילו להתנהגות כזו שאובייקט עדיין קיים במיקום המקורי שלו, למרות שהוא שציירתם על מיקום אחר במסך. ב-Android 3.0, נכסים חדשים נוספו שיטות getter ו-setter כדי לבטל את החיסרון הזה.

מערכת האנימציה של המאפיין יכול להנפיש את תצוגות המסך על ידי שינוי המאפיינים בפועל באובייקטים של View. לחשבון בנוסף, תצוגות מפורטות גם קוראות אוטומטית לinvalidate() לרענון המסך בכל פעם שהמאפיינים שלו משתנים. המאפיינים החדשים במחלקה View שמאפשרים אנימציות של מאפיינים הם:

  • translationX ו-translationY: המאפיינים האלה קובעים איפה התצוגה ממוקמת כדלתא מהקואורדינטות השמאליות והעליונות שלה, שנקבעות על ידי הפריסה מאגר תגים.
  • rotation, rotationX ו-rotationY: הנכסים האלה לשלוט בסבב בתצוגה דו-ממדית (נכס rotation) ובתלת-ממד סביב נקודת הציר.
  • scaleX ו-scaleY: המאפיינים האלה שולטים בהתאמה לדו-ממדית של להציג מסביב לנקודת הציר שלה.
  • pivotX ו-pivotY: המאפיינים האלה קובעים את המיקום של נקודת הציר, שסביבה מתרחשים שינויים של הסיבוב וההתאמה. כברירת מחדל, טבלת הציר נמצאת במרכז האובייקט.
  • x ו-y: אלה מאפיינים פשוטים של כלי עזר, שמתארים את המיקום הסופי של התצוגה במאגר, כסכום של הערכים השמאליים והעליונים ו-TranslateX ו-TranslateY.
  • 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 של תצוגה מפורטת.

אובייקטים מרובים של 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 מאפשרת להשתמש שוב באנימציות בקלות בכמה פעילויות ולערוך בקלות את רצף האנימציה.

כדי להבדיל בין קובצי אנימציה שמשתמשים בממשקי ה-API עם האנימציה של הנכס החדש לבין קובצי אנימציה שמשתמשים ב- מסגרת צפייה באנימציה מדור קודם, החל מ-Android 3.1, יש לשמור בספרייה res/animator/ את קובצי ה-XML לאנימציות של נכסים.

במחלקות האנימציה הבאות של המאפיינים יש תמיכה בהצהרת 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 להגדרת אנימציות של מאפיינים, ראו אנימציה משאבים נוספים .

השפעות פוטנציאליות על הביצועים של ממשק המשתמש

אנימטורים שמעדכנים את ממשק המשתמש גורמים לפעולת רינדור נוספת לכל פריים שהאנימציה רצה. לכן, שימוש באנימציות עתירות משאבים עלולה להשפיע לרעה על ביצועי האפליקציה שלכם.

העבודה הנדרשת כדי להוסיף אנימציה לממשק המשתמש מתווספת לשלב האנימציה של בצינור עיבוד הנתונים. אפשר לבדוק אם האנימציות משפיעות על של האפליקציה שלך על ידי הפעלת רינדור GPU של פרופיל לעקוב אחרי שלב האנימציה. למידע נוסף, ראו עיבוד GPU של פרופיל בהדרכה מפורטת.