העברת תצוגה עם אנימציה

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

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

שינוי מיקום התצוגה באמצעות ObjectAnimator

ObjectAnimator דרך ה-API אפשר לשנות את המאפיינים של תצוגה מפורטת עם משך זמן ספציפי. הוא מכיל שיטות סטטיות ליצירת מופעים של ObjectAnimator, בהתאם איזה סוג של מאפיין אתם מוסיפים אנימציה. כאשר ממקמים מחדש את התצוגות המסך, משתמשים במאפיינים translationX ו-translationY.

הנה דוגמה של ObjectAnimator שמזיז את התצוגה למיקום 100 פיקסלים מצד שמאל של המסך ב-2 שניות:

Kotlin

ObjectAnimator.ofFloat(view, "translationX", 100f).apply {
    duration = 2000
    start()
}

Java

ObjectAnimator animation = ObjectAnimator.ofFloat(view, "translationX", 100f);
animation.setDuration(2000);
animation.start();

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

השיטה הבאה מציינת כמה זמן האנימציה נמשכת, באלפיות השנייה. כאן לדוגמה, האנימציה פועלת במשך שתי שניות (2,000 אלפיות השנייה).

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

למידע נוסף על השימוש ב-ObjectAnimator, ראו אנימציה באמצעות ObjectAnimator.

הוספת תנועה מעוקלת

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

הגדרת הנתיב האישי

המחלקה ObjectAnimator כוללת בנאים שמאפשרים להנפיש קואורדינטות באמצעות שני מאפיינים או יותר בו-זמנית עם נתיב. עבור למשל, האנימטור הבא משתמש אובייקט Path להנפשה של ה-X וה-Y המאפיינים של תצוגה מפורטת:

Kotlin

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    val path = Path().apply {
        arcTo(0f, 0f, 1000f, 1000f, 270f, -180f, true)
    }
    val animator = ObjectAnimator.ofFloat(view, View.X, View.Y, path).apply {
        duration = 2000
        start()
    }
} else {
    // Create animator without using curved path
}

Java

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  Path path = new Path();
  path.arcTo(0f, 0f, 1000f, 1000f, 270f, -180f, true);
  ObjectAnimator animator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
  animator.setDuration(2000);
  animator.start();
} else {
  // Create animator without using curved path
}

כך נראית אנימציית קשת:

איור 1. אנימציה של נתיב מעוקל.

Interpolator הוא יישום של עקומת התאמה. לצפייה מסמכי תיעוד של עיצוב Material Design מפורט מידע נוסף על המושג של עקומות ההתאמה. Interpolator מגדיר כיצד ערכים ספציפיים באנימציה מחושבים כפונקציה של בזמן האימון. המערכת מספקת משאבי XML לשלוש העקומות הבסיסיות מפרט של עיצוב חומר:

  • @interpolator/fast_out_linear_in.xml
  • @interpolator/fast_out_slow_in.xml
  • @interpolator/linear_out_slow_in.xml

שימוש ב-PathInterpolator

PathInterpolator class הוא אינטרפולטור שהושק ב-Android 5.0 (API 21). מבוסס על Bézier עקומת או אובייקט Path. הדוגמאות ל-Android במסמכי התיעוד של Material Design עבור התאמה לצפייה להשתמש ב-PathInterpolator.

ל-PathInterpolator יש בנאים המבוססים על סוגים שונים של עקומות של Bézier. לכל עקומות Bézier יש נקודות התחלה וסיום קבועות ב-(0,0) וב-(1,1), בהתאמה. הארגומנטים האחרים של ה-constructor תלויים בסוג Bézier שהעקומה נוצרת.

לדוגמה, לעקומת Bézier ריבועית רק קואורדינטות X ו-Y של נקודת בקרה אחת נחוצים:

Kotlin

val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    PathInterpolator(0.67f, 0.33f)
} else {
    LinearInterpolator()
}

Java

Interpolator myInterpolator = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  myInterpolator = new PathInterpolator(0.67f, 0.33f);
} else {
  myInterpolator = new LinearInterpolator();
}

הפעולה הזו יוצרת עקומת התאמה שמתחילה במהירות והולכת ופוחתת ככל שהיא מתקרב לסוף.

באופן דומה, ל-constructor של cubic Bézier יש נקודות התחלה וסיום קבועות, אבל נדרשות שתי נקודות בקרה:

Kotlin

val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    PathInterpolator(0.5f, 0.7f, 0.1f, 1.0f)
} else {
    LinearInterpolator()
}

Java

Interpolator myInterpolator = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  myInterpolator = new PathInterpolator(0.5f, 0.7f, 0.1f, 1.0f);
} else {
  myInterpolator = new LinearInterpolator();
}

זהו יישום של עיצוב Material Design שמודגש האטה עקומה.

כדי להשיג שליטה טובה יותר, אפשר להשתמש בפונקציה Path שרירותית כדי להגדיר את העקומה:

Kotlin

val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  val path = Path().apply {
    moveTo(0.0f, 0.0f)
    cubicTo(0.5f, 0.7f, 0.1f, 1.0f, 1.0f, 1.0f)
  }
  PathInterpolator(path)
} else {
  LinearInterpolator()
}

Java

Interpolator myInterpolator = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  Path path = new Path();
  path.moveTo(0.0f, 0.0f);
  path.cubicTo(0.5f, 0.7f, 0.1f, 1.0f, 1.0f, 1.0f);
  myInterpolator = new PathInterpolator(path);
} else {
  myInterpolator = new LinearInterpolator();
}

הפעולה הזו יוצרת את אותה עקומת התאמה כמו בדוגמה של cubic Bézier, אבל היא משתמשת יש גם אפשרות Path.

אפשר גם להגדיר אינטרפולטור נתיב כמשאב XML:

<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    android:controlX1="0.5"
    android:controlY1="0.7"
    android:controlX2="0.1f"
    android:controlY2="1.0f"/>

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

Kotlin

val animation = ObjectAnimator.ofFloat(view, "translationX", 100f).apply {
    interpolator = myInterpolator
    start()
}

Java

ObjectAnimator animation = ObjectAnimator.ofFloat(view, "translationX", 100f);
animation.setInterpolator(myInterpolator);
animation.start();