מערכת האנימציה של המאפיינים היא מסגרת אפקטיבית שמאפשרת כדי להנפיש כמעט כל דבר. אפשר להגדיר אנימציה כדי לשנות כל מאפיין אובייקט לאורך זמן, בין אם הוא קשור למסך או לא. אנימציה של נכס משנה נכס (שדה באובייקט) לאורך פרק זמן שצוין. כדי להוסיף אנימציה לפריט כלשהו, צריך לציין מאפיין האובייקט שרוצים להוסיף לו אנימציה, כמו מיקום האובייקט במסך, משך הזמן שתרצו ליצור לו אנימציה, ואילו ערכים תרצו להנפיש.
מערכת האנימציה של המאפיינים מאפשרת להגדיר את המאפיינים הבאים של אנימציה:
- משך זמן: אפשר להגדיר את משך האנימציה. אורך ברירת המחדל הוא 300 אלפיות השנייה.
- אינטרפולציה של זמן: אפשר לציין איך ערכי הנכס מחושבים הפונקציה של הזמן שחלף עכשיו באנימציה.
- ספירה והתנהגות של אנימציה: ניתן לציין אם אנימציה תחזור על עצמה מגיע לסוף משך הזמן של האנימציה וכמה פעמים לחזור על אותה אנימציה. אפשר גם לציין אם רוצים שהאנימציה תופעל בסדר הפוך. המערכת מגדירה אותו כדי להפוך הפעלות את האנימציה קדימה ואז אחורה שוב ושוב, עד שמגיעים למספר החזרות.
- ערכות של אנימטורים: אפשר לקבץ אנימציות לערכות לוגיות שפועלות יחד או ברצף או לאחר עיכובים מסוימים.
- השהיה ברענון פריימים: אפשר לציין באיזו תדירות לרענן את הפריימים באנימציה. ברירת המחדל מוגדרת לרענון כל 10 אלפיות השנייה, אבל המהירות שבה האפליקציה יכולה לרענן פריימים היא תלוי בסופו של דבר במידת העומס הכוללת של המערכת ובמהירות שבה המערכת יכולה לטפל בטיימר הבסיסי.
כדי לראות דוגמה מלאה לאנימציה של נכס, אפשר לעיין ב
כיתה אחת (ChangeColor
) בהתאמה אישית
לדוגמה ב-GitHub.
איך פועלת האנימציה של הנכס
נתחיל עם דוגמה פשוטה: איך אנימציה עובדת. איור 1 מציג
אובייקט היפותטי שעובר אנימציה באמצעות המאפיין x
שלו, שמייצג
המיקום האופקי במסך. משך האנימציה מוגדר ל-40 אלפיות השנייה והמרחק
לנסיעה היא 40 פיקסלים. כל 10 אלפיות השנייה, שהוא קצב הרענון של הפריימים שמוגדר כברירת מחדל, האובייקט זז
לרוחב של 10 פיקסלים. בסוף 40 אלפיות השנייה, האנימציה נפסקת והאובייקט מסתיים ב-
מיקום אופקי 40. זוהי דוגמה לאנימציה עם אינטרפולציה ליניארית, כלומר
האובייקט נע במהירות קבועה.
אפשר גם להגדיר אנימציות כך שתהיה להן אינטרפולציה לא ליניארית. איור 2 ממחיש אובייקט היפותטי שמאיץ בתחילת האנימציה והופך לאט יותר סוף האנימציה. האובייקט עדיין זז 40 פיקסלים ב-40 אלפיות השנייה, אבל באופן לא לינארי. ב בהתחלה, האנימציה הזו מאיצה עד לנקודת חצי הדרך ולאחר מכן מורידה נקודת האמצע של הנקודה עד לסוף האנימציה. כמו שרואים באיור 2, המרחק שעברת בהתחלה ובסוף של האנימציה פחות מאשר באמצע.
עכשיו נראה בפירוט איך הרכיבים החשובים במערכת האנימציה של המאפיינים הפונקציה תחשב אנימציות כמו אלו שמתוארות למעלה. איור 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
:
דרגה | תיאור |
---|---|
ValueAnimator |
מנוע התזמון הראשי לאנימציה של הנכס, שמחשב גם את הערכים של
להנפשה. יש לו את כל הפונקציונליות העיקרית שמחשבת את האנימציה
ומכיל את פרטי התזמון של כל אנימציה, מידע שמציין אם
אנימציות חוזרות, מאזינים שמקבלים אירועי עדכון ואפשרות להגדיר פקודות מותאמות אישית
כדי להעריך אותם. קיימים שני חלקים במאפיינים של אנימציה: חישוב של תוכן אנימציה
והגדרת הערכים האלה באובייקט ובמאפיין שמונפשים. החלק השני לא נשמר ב-ValueAnimator , לכן עליך להאזין
לעדכונים בערכים המחושבים לפי ValueAnimator ו-
לשנות את האובייקטים שאותם אתם רוצים להוסיף לאנימציה בעזרת הלוגיקה שלכם. מעבר לקטע על
הוספת אנימציה עם ValueAnimator כדי לקבל מידע נוסף. |
ObjectAnimator |
תת-מחלקה של ValueAnimator שמאפשרת להגדיר יעד
של אובייקט ואובייקט להנפשה. הכיתה מעדכנת את הנכס בהתאם כאשר
ומחשב ערך חדש עבור האנימציה. אתם רוצים להשתמש
ObjectAnimator ברוב המקרים,
כי הוא הופך את התהליך של הוספת אנימציה לערכים של אובייקטי יעד, הרבה יותר קל. אבל, לפעמים
לפעמים רוצים להשתמש ישירות באפליקציה ValueAnimator , כי ב-ObjectAnimator יש עוד כמה הגבלות, כמו דרישה
methods של רכיב גישה שיהיו באובייקט היעד. |
AnimatorSet |
מספקת מנגנון לקיבוץ אנימציות יחד כדי שיפעלו יחסים ביניהן. אפשר להגדיר את האנימציות שיופעלו ביחד, ברצף או אחריו עיכוב מוגדר. ניתן לעיין בקטע בנושא כוריאוגרפיה של מספר מודעות אנימציות עם ערכות אנימטור כדי לקבל מידע נוסף. |
מעריכים אומרים למערכת האנימציה של המאפיינים איך לחשב את הערכים של מימד נתון
לנכס. הן לוקחות את נתוני התזמון שסופקו על ידי Animator
class, את ערך ההתחלה והסיום של האנימציה, ומחשב את הערכים המונפשים של המאפיין
על סמך הנתונים האלה. מערכת האנימציה של המאפיינים מספקת את הבודקים הבאים:
כיתה/ממשק | תיאור |
---|---|
IntEvaluator |
כלי ההערכה שמוגדר כברירת מחדל לחישוב הערכים של נכסים של int . |
FloatEvaluator |
כלי ההערכה שמוגדר כברירת מחדל לחישוב הערכים של נכסים של float . |
ArgbEvaluator |
בודק ברירת המחדל לחישוב ערכים למאפייני צבע שמיוצגים לערכים הקסדצימליים. |
TypeEvaluator |
ממשק שמאפשר לכם ליצור מעריך משלכם. אם אתם יוצרים אנימציה של
מאפיין אובייקט שלא int , float או צבע,
עליכם להטמיע את הממשק TypeEvaluator כדי לציין איך
כדי לחשב את הערכים המונפשים של מאפיין האובייקט. אפשר גם לציין TypeEvaluator מותאם אישית עבור int , float וצבע
אם רוצים לעבד את הסוגים האלה באופן שונה מהתנהגות ברירת המחדל.
מידע נוסף זמין בקטע שימוש ב-TypeEvaluator.
מידע על האופן שבו ניתן לכתוב מעריך מותאם אישית. |
אינטרפולטור זמן מגדיר איך ערכים ספציפיים באנימציה מחושבים
הוא פונקציה של הזמן. לדוגמה, תוכלו לציין שהאנימציות יתרחשו באופן לינארי
אנימציה. כלומר, האנימציה זזה באופן שווה לאורך כל הזמן, או שאפשר לציין אנימציות.
להשתמש בזמן לא ליניארי, לדוגמה, להאיץ בהתחלה ולהפחית את התנועה
סוף האנימציה. בטבלה 3 מתוארים האינטרפולטורים שנכללים ב-android.view.animation
. אם אף אחד מהאינטרפולטורים שסופקו לא מתאים
לצרכים שלך, יש להטמיע את הממשק של TimeInterpolator
וליצור ממשק משלך. לקבלת מידע נוסף על כתיבה של נתוני אינטרפולטורים, ראו שימוש באינטרפולטורים.
באינטרפולטור.
כיתה/ממשק | תיאור |
---|---|
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
, צריכה להיות לך methodgetFoo()
. - השיטות של getter (במידת הצורך) והשיטה הזו של הנכס שמונפשות חייבות
פועלים על אותו סוג כמו ערכי ההתחלה והסיום שציינתם ל-
ObjectAnimator
. לדוגמה, אתם צריכיםtargetObject.setPropName(float)
ו-targetObject.getPropName()
אם יוצרים את ה-ObjectAnimator
הבא:ObjectAnimator.ofFloat(targetObject, "propName", 1f)
- בהתאם למאפיין או לאובייקט שאתם יוצרים באנימציה, ייתכן שתצטרכו לקרוא ל-method
invalidate()
בתצוגה מפורטת כדי לאלץ את המסך לצייר מחדש את עצמו באמצעות ערכים מונפשים מעודכנים. עושים זאתonAnimationUpdate()
קריאה חוזרת. לדוגמה, אנימציה של מאפיין הצבע של אובייקט שניתן להזזה גורמת רק לעדכונים כשהאובייקט משרטט מחדש את עצמו. כל מאפייני הנכסים בתצוגה מפורטת, כמוsetAlpha()
ו-setTranslationX()
לבטל את תוקף התצוגה בצורה נכונה, כך שלא צריך לבטל את התוקף של התצוגה במהלך קריאה עם ערכים חדשים. למידע נוסף על מאזינים, אפשר לעיין בקטע שעוסק מאזיני אנימציה.
כוריאוגרף של מספר אנימציות באמצעות 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.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 של התצוגה בזמן הלחיצה:
<?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 הבאים:
-
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 של פרופיל בהדרכה מפורטת.