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

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

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

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

  • משך זמן: אפשר להגדיר את משך האנימציה. אורך ברירת המחדל הוא 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, מכיוון שהאנימציה מאיצה לאט, החלק המשוער, בערך 0.15, קטן מהחלק שחלף, 0.25, בזמן t = 10 אלפיות השנייה. באיור 1, החלק המשוער תמיד זהה לחלק שחלף.

כאשר מחושב השבר המחושב, ValueAnimator הפעלות את TypeEvaluator המתאים, כדי לחשב את הערך את המאפיין שאתם יוצרים באנימציה, על סמך השבר המחושב, ערך ההתחלה הערך הסופי של האנימציה. לדוגמה, באיור 2, החלק המחושב היה 0.15 בזמן t = 10ms, כך שהערך של המאפיין באותו זמן יהיה 0.15 x (40 - 0), או 6.

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

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

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

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

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

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

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

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

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

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

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

לחלופין, כדי להקצות אנימטור של רשימת מצבים לתצוגה בקוד, משתמשים ב-method‏ AnimatorInflater.loadStateListAnimator() ומקצים את האנימטור לתצוגה באמצעות ה-method‏ View.setStateListAnimator().

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

לדוגמה, בהמשך מוצגת השוואה בין האופן שבו המפַתח (interpolator) שמוגדר כברירת מחדל, 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;
}

הטבלה הבאה מציגה את הערכים המשוערים שמחושבים על ידי אינטרפולטורים לאנימציה שנמשכת 1,000 אלפיות השנייה:

זמן שחלף באלפיות השנייה שבר חולף/שבר משוער (לינארי) שבר אינטרפולציה (האצה/האטה)
0 0 0
200 2. .1
400 4. 345.
600 6. .654
800 0.8 9.
1000 1 1

כפי שמוצג בטבלה, הפונקציה LinearInterpolator משנה את הערכים באותה מהירות, 0.2 לכל 200 אלפיות השנייה שחולפות. AccelerateDecelerateInterpolator משנה את הערכים מהר יותר מ-LinearInterpolator בין 200 אלפיות השנייה ל-600 אלפיות השנייה, ולאט יותר בין 600 אלפיות השנייה לבין 1,000 אלפיות השנייה.

ציון של נקודות מפתח

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

כדי ליצור אובייקט Keyframe, צריך להשתמש באחד מהמפעלים ofInt(), ofFloat() או ofObject() כדי לקבל את הסוג המתאים של Keyframe. לאחר מכן, קוראים ל-method של המפעל 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 כדי לבטל את החיסרון הזה.

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

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

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

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

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

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