יצירה של אנימציית מעבר בהתאמה אישית

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

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

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

בדף הזה תלמדו איך לתעד ערכים של נכסים וליצור אנימציות כדי ליצור מעברים מותאמים אישית.

הרחבת הכיתה Transition

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

KotlinJava
class CustomTransition : Transition() {

    override fun captureStartValues(transitionValues: TransitionValues) {}

    override fun captureEndValues(transitionValues: TransitionValues) {}

    override fun createAnimator(
        sceneRoot: ViewGroup,
        startValues: TransitionValues?,
        endValues: TransitionValues?
    ): Animator? {}

}
public class CustomTransition extends Transition {

    @Override
    public void captureStartValues(TransitionValues values) {}

    @Override
    public void captureEndValues(TransitionValues values) {}

    @Override
    public Animator createAnimator(ViewGroup sceneRoot,
                                   TransitionValues startValues,
                                   TransitionValues endValues) {}
}

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

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

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

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

תיעוד ערכי ההתחלה

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

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

package_name:transition_name:property_name

קטע הקוד הבא מציג הטמעה של הפונקציה captureStartValues():

KotlinJava
class CustomTransition : Transition() {

    // Define a key for storing a property value in
    // TransitionValues.values with the syntax
    // package_name:transition_class:property_name to avoid collisions
    private val PROPNAME_BACKGROUND = "com.example.android.customtransition:CustomTransition:background"

    override fun captureStartValues(transitionValues: TransitionValues) {
        // Call the convenience method captureValues
        captureValues(transitionValues)
    }

    // For the view in transitionValues.view, get the values you
    // want and put them in transitionValues.values
    private fun captureValues(transitionValues: TransitionValues) {
        // Get a reference to the view
        val view = transitionValues.view
        // Store its background property in the values map
        transitionValues.values[PROPNAME_BACKGROUND] = view.background
    }

    ...

}
public class CustomTransition extends Transition {

    // Define a key for storing a property value in
    // TransitionValues.values with the syntax
    // package_name:transition_class:property_name to avoid collisions
    private static final String PROPNAME_BACKGROUND =
            "com.example.android.customtransition:CustomTransition:background";

    @Override
    public void captureStartValues(TransitionValues transitionValues) {
        // Call the convenience method captureValues
        captureValues(transitionValues);
    }


    // For the view in transitionValues.view, get the values you
    // want and put them in transitionValues.values
    private void captureValues(TransitionValues transitionValues) {
        // Get a reference to the view
        View view = transitionValues.view;
        // Store its background property in the values map
        transitionValues.values.put(PROPNAME_BACKGROUND, view.getBackground());
    }
    ...
}

תיעוד ערכים סופיים

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

קטע הקוד הבא מציג הטמעה של הפונקציה captureEndValues():

KotlinJava
override fun captureEndValues(transitionValues: TransitionValues) {
    captureValues(transitionValues)
}
@Override
public void captureEndValues(TransitionValues transitionValues) {
    captureValues(transitionValues);
}

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

יצירת אנימטור בהתאמה אישית

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

מספר הפעמים שהמסגרת קוראת לפונקציה createAnimator() תלוי בשינויים שמתרחשים בין הסצנה ההתחלתית לסצנה הסופית.

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

לתצוגות יעד שקיימות גם בסצנה ההתחלתית וגם בסצנה הסופית, המסגרת מספקת אובייקט TransitionValues גם לארגומנט startValues וגם לארגומנט endValues. בתצוגות היעד שקיימות רק בסצנה ההתחלתית או בסצנה הסופית, המסגרת מספקת אובייקט TransitionValues לארגומנט התואם ואובייקט null לארגומנט השני.

כדי להטמיע את הפונקציה createAnimator(ViewGroup, TransitionValues, TransitionValues) כשיוצרים מעבר מותאם אישית, משתמשים בערכים של מאפייני התצוגה שצילמתם כדי ליצור אובייקט Animator ולהחזיר אותו למסגרת. דוגמה להטמעה מופיעה בכיתה ChangeColor בדוגמה CustomTransition. למידע נוסף על אנימטורים של מאפיינים, ראו אנימציה של מאפיינים.

החלת העברה בהתאמה אישית

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