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

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

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

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

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

הרחבת המחלקה Transition

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

Kotlin

class CustomTransition : Transition() {

    override fun captureStartValues(transitionValues: TransitionValues) {}

    override fun captureEndValues(transitionValues: TransitionValues) {}

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

}

Java

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) {}
}

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

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

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

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

צילום ערכי התחלה

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

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

package_name:transition_name:property_name

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

Kotlin

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
    }

    ...

}

Java

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():

Kotlin

override fun captureEndValues(transitionValues: TransitionValues) {
    captureValues(transitionValues)
}

Java

@Override
public void captureEndValues(TransitionValues transitionValues) {
    captureValues(transitionValues);
}

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

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

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

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

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

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

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

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

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