התחלת פעילות באמצעות אנימציה

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

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

איור 1. מעבר עם רכיבים משותפים.

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

‫Android תומך במעברים הבאים של כניסה ויציאה:

  • explode: תנועת הצפיות היא לכיוון מרכז הסצנה או הרחק ממנו.
  • slide: מזיז את התצוגות פנימה או החוצה מאחד הקצוות של הסצנה.
  • fade: מוסיף או מסיר תצוגה מהסצנה על ידי שינוי השקיפות שלה.

כל מעבר שמרחיב את המחלקה Visibility נתמך כמעבר כניסה או יציאה. מידע נוסף זמין במאמר בנושא הפניית API ל-class‏ Transition.

ב-Android יש תמיכה גם במעברים של הרכיבים המשותפים הבאים:

  • changeBounds: מפעיל אנימציה של השינויים בגבולות הפריסה של תצוגות היעד.
  • changeClipBounds: מפעיל אנימציה של השינויים בגבולות הקליפ של תצוגות היעד.
  • changeTransform: מציג אנימציה של השינויים בגודל ובסיבוב של תצוגות היעד.
  • changeImageTransform: יוצר אנימציה של השינויים בגודל ובקנה המידה של תמונות היעד.

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

איור 2. מעבר בין סצנות עם רכיב משותף אחד.

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

בדיקת גרסת המערכת

ממשקי ה-API של מעברי הפעילות זמינים ב-Android 5.0‏ (API 21) ואילך. כדי לשמור על תאימות לגרסאות קודמות של Android, צריך לבדוק את המערכת version בזמן הריצה לפני שמפעילים את ממשקי ה-API של אחת מהתכונות האלה:

Kotlin

// Check if we're running on Android 5.0 or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // Apply activity transition
} else {
    // Swap without transition
}

Java

// Check if we're running on Android 5.0 or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // Apply activity transition
} else {
    // Swap without transition
}

הגדרת מעברים בהתאמה אישית

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

<style name="BaseAppTheme" parent="android:Theme.Material">
  <!-- enable window content transitions -->
  <item name="android:windowActivityTransitions">true</item>

  <!-- specify enter and exit transitions -->
  <item name="android:windowEnterTransition">@transition/explode</item>
  <item name="android:windowExitTransition">@transition/explode</item>

  <!-- specify shared element transitions -->
  <item name="android:windowSharedElementEnterTransition">
    @transition/change_image_transform</item>
  <item name="android:windowSharedElementExitTransition">
    @transition/change_image_transform</item>
</style>

המעבר change_image_transform בדוגמה הזו מוגדר כך:

<!-- res/transition/change_image_transform.xml -->
<!-- (see also Shared Transitions below) -->
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
  <changeImageTransform/>
</transitionSet>

הרכיב changeImageTransform תואם למחלקה ChangeImageTransform. מידע נוסף זמין במאמר בנושא הפניית ה-API של Transition.

כדי להפעיל את המעברים בין התוכן של החלונות בקוד, קוראים לפונקציה Window.requestFeature():

Kotlin

// Inside your activity (if you did not enable transitions in your theme)
with(window) {
    requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)

    // Set an exit transition
    exitTransition = Explode()
}

Java

// Inside your activity (if you did not enable transitions in your theme)
getWindow().requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);

// Set an exit transition
getWindow().setExitTransition(new Explode());

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

הפונקציות setExitTransition() ו-setSharedElementExitTransition() מגדירות את מעבר היציאה של הפעילות שקוראת לפונקציה. הפונקציות setEnterTransition() ו-setSharedElementEnterTransition() מגדירות את אנימציית המעבר של הפעילות שאליה מתבצעת הקריאה.

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

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

איך מתחילים פעילויות באמצעות מעברים

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

Kotlin

startActivity(intent,
              ActivityOptions.makeSceneTransitionAnimation(this).toBundle())

Java

startActivity(intent,
              ActivityOptions.makeSceneTransitionAnimation(this).toBundle());

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

איך מתחילים פעילויות עם רכיבים משותפים

כדי ליצור אנימציה של מעבר מסך בין שתי פעילויות שיש להן רכיב משותף:

  1. הפעלת מעברים בין תכנים בחלון בעיצוב.
  2. מציינים מעבר של רכיבים משותפים בסגנון.
  3. מגדירים את המעבר כמשאב XML.
  4. מקצים שם נפוץ לאלמנטים המשותפים בשני הפריסות באמצעות המאפיין android:transitionName.
  5. משתמשים בפונקציה ActivityOptions.makeSceneTransitionAnimation().

Kotlin

// Get the element that receives the click event
val imgContainerView = findViewById<View>(R.id.img_container)

// Get the common element for the transition in this activity
val androidRobotView = findViewById<View>(R.id.image_small)

// Define a click listener
imgContainerView.setOnClickListener( {
    val intent = Intent(this, Activity2::class.java)
    // Create the transition animation - the images in the layouts
    // of both activities are defined with android:transitionName="robot"
    val options = ActivityOptions
            .makeSceneTransitionAnimation(this, androidRobotView, "robot")
    // Start the new activity
    startActivity(intent, options.toBundle())
})

Java

// Get the element that receives the click event
final View imgContainerView = findViewById(R.id.img_container);

// Get the common element for the transition in this activity
final View androidRobotView = findViewById(R.id.image_small);

// Define a click listener
imgContainerView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(this, Activity2.class);
        // Create the transition animation - the images in the layouts
        // of both activities are defined with android:transitionName="robot"
        ActivityOptions options = ActivityOptions
            .makeSceneTransitionAnimation(this, androidRobotView, "robot");
        // Start the new activity
        startActivity(intent, options.toBundle());
    }
});

בתצוגות דינמיות משותפות שנוצרות בקוד, משתמשים בפונקציה View.setTransitionName() כדי לציין שם רכיב משותף בשתי הפעילויות.

כדי להפוך את האנימציה של מעבר הסצנה כשמסיימים את הפעילות השנייה, קוראים לפונקציה Activity.finishAfterTransition() במקום Activity.finish().

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

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

Kotlin

// Rename the Pair class from the Android framework to avoid a name clash
import android.util.Pair as UtilPair
...
val options = ActivityOptions.makeSceneTransitionAnimation(this,
        UtilPair.create(view1, "agreedName1"),
        UtilPair.create(view2, "agreedName2"))

Java

ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
        Pair.create(view1, "agreedName1"),
        Pair.create(view2, "agreedName2"));