הוספת תמיכה בתנועת החזרה החזויה

איור 1. Mockup של המראה והתחושה של התנועה החזרה החזוי בטלפון

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

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

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

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

כדי לתמוך בתנועת החזרה החזויה, צריך לעדכן את האפליקציה באמצעות התאימות לאחור OnBackPressedCallback AppCompat 1.6.0-alpha05 (AndroidX) או API מתקדם יותר, או להשתמש ב-API החדש של הפלטפורמה OnBackInvokedCallback. רוב האפליקציות משתמשות ב-AndroidX API עם תאימות לאחור.

העדכון הזה מספק נתיב העברה כדי ליירט כראוי את הניווט לאחור. לשם כך, צריך להחליף את ניתוחי הנתונים לאחור מ-KeyEvent.KEYCODE_BACK וכל הכיתות עם שיטות onBackPressed, כמו Activity ו-Dialog, בממשקי ה-API החדשים של המערכת לניווט לאחור.

Codelab וסרטון מ-Google I/O

בנוסף לשימוש במסמכי התיעוד שבדף הזה, כדאי לנסות את ה-codelab שלנו. הוא מספק הטמעה של תרחיש לדוגמה של WebView שמטפל בתנועת החזרה החזוי באמצעות ממשקי AndroidX Activity API.

אפשר גם לצפות בסרטון של Google I/O, שכולל דוגמאות נוספות להטמעת ממשקי ה-API של AndroidX ושל הפלטפורמה.

עדכון אפליקציה שמשתמשת בניווט ברירת המחדל אחורה

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

אם האפליקציה שלכם משתמשת ב-Fragments או ברכיב הניווט, עליכם לשדרג גם ל-AndroidX Activity 1.6.0-alpha05 ואילך.

עדכון אפליקציה שמשתמשת בניווט חזרה בהתאמה אישית

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

האפליקציה שלכם משתמשת ב-AndroidX איך האפליקציה מטפלת בניווט לאחור נתיב ההעברה המומלץ (קישור בדף הזה)
כן ממשקי API של AndroidX העברת הטמעה קיימת של AndroidX לאחור
ממשקי API לא נתמכים של פלטפורמות העברת אפליקציית AndroidX שמכילה ממשקי API לניווט לאחור שלא נתמכים לממשקי API של AndroidX
לא ממשקי API של פלטפורמות לא נתמכות, שניתן להעביר העברת אפליקציה שמשתמשת בממשקי API לניווט לאחור שלא נתמכים לממשקי API של פלטפורמות
ממשקי API של פלטפורמות לא נתמכות, אבל לא ניתן להעביר אותם דחיית ההסכמה עד שהתכונה הזו תהפוך לתכונה חובה

העברה של הטמעת ניווט אחורה ב-AndroidX

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

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

  1. כדי להבטיח שממשקי API שכבר משתמשים בממשקי API של OnBackPressedDispatcher (כמו Fragments ורכיב הניווט) יפעלו בצורה חלקה עם תנועת החיזוי לחזרה אחורה, צריך לשדרג ל-AndroidX Activity 1.6.0-alpha05.

    // In your build.gradle file:
    dependencies {
    
    // Add this in addition to your other dependencies
    implementation "androidx.activity:activity:1.6.0-alpha05"
    
  2. מאשרים את השימוש בתכונה 'חיזוי תנועת החזרה', כפי שמתואר בדף הזה.

איך מעבירים אפליקציה של AndroidX שמכילה ממשקי API לא נתמכים של ניווט לאחור לממשקי API של AndroidX

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

כדי להעביר ממשקי API לא נתמכים לממשקי API של AndroidX:

  1. מעבירים את הלוגיקה לטיפול בבקשות Back של המערכת אל OnBackPressedDispatcher של AndroidX באמצעות הטמעה של OnBackPressedCallback. להנחיות מפורטות, ראו הוספת ניווט מותאם אישית אחורה.

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

  3. אפשר להפסיק ליירט אירועים חוזרים דרך OnBackPressed או KeyEvent.KEYCODE_BACK.

  4. הקפידו לשדרג ל-AndroidX Activity 1.6.0-alpha05.

    // In your build.gradle file:
    dependencies {
    
    // Add this in addition to your other dependencies
    implementation "androidx.activity:activity:1.6.0-alpha05"
    
  5. אחרי שהאפליקציה תועבר, תוכלו להביע הסכמה לתנועת החזרה החזוי (כפי שמתואר בדף הזה) כדי לראות את האנימציה של החזרה למסך הבית.

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

אם באפליקציה שלכם אי אפשר להשתמש בספריות AndroidX, ובמקום זאת אתם מטמיעים ניווט חזרה בהתאמה אישית או מפנים אליו באמצעות ממשקי ה-API שלא נתמכים, תצטרכו לעבור לממשק ה-API של הפלטפורמה OnBackInvokedCallback.

כדי להעביר ממשקי API שלא נתמכים ל-API של הפלטפורמה:

  1. משתמשים ב-API החדש OnBackInvokedCallback במכשירים עם Android מגרסה 13 ואילך, ומשתמשים בממשקי ה-API ללא תמיכה במכשירים עם Android מגרסה 12 ומטה.

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

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

    דוגמה להעברת לוגיקה מ-onBackPressed:

    Kotlin

    @Override
    fun onCreate() {
        if (BuildCompat.isAtLeastT()) {
            onBackInvokedDispatcher.registerOnBackInvokedCallback(
                OnBackInvokedDispatcher.PRIORITY_DEFAULT
            ) {
                /**
                 * onBackPressed logic goes here. For instance:
                 * Prevents closing the app to go home screen when in the
                 * middle of entering data to a form
                 * or from accidentally leaving a fragment with a WebView in it
                 *
                 * Unregistering the callback to stop intercepting the back gesture:
                 * When the user transitions to the topmost screen (activity, fragment)
                 * in the BackStack, unregister the callback by using
                 * OnBackInvokeDispatcher.unregisterOnBackInvokedCallback
                 * (https://developer.android.com/reference/kotlin/android/window/OnBackInvokedDispatcher#unregisteronbackinvokedcallback)
                 */
            }
        }
    }

    Java

    @Override
    void onCreate() {
      if (BuildCompat.isAtLeastT()) {
        getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
            OnBackInvokedDispatcher.PRIORITY_DEFAULT,
            () -> {
              /**
               * onBackPressed logic goes here - For instance:
               * Prevents closing the app to go home screen when in the
               * middle of entering data to a form
               * or from accidentally leaving a fragment with a WebView in it
               *
               * Unregistering the callback to stop intercepting the back gesture:
               * When the user transitions to the topmost screen (activity, fragment)
               * in the BackStack, unregister the callback by using
               * OnBackInvokeDispatcher.unregisterOnBackInvokedCallback
               * (https://developer.android.com/reference/kotlin/android/view/OnBackInvokedDispatcher#unregisteronbackinvokedcallback)
               */
            }
        );
      }
    }
  4. הפסקת ניתוב אירועי Back דרך OnBackPressed או KeyEvent.KEYCODE_BACK ב-Android 13 ואילך.

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

אפשר לרשום OnBackInvokedCallback באמצעות PRIORITY_DEFAULT או PRIORITY_OVERLAY, אבל האפשרות הזו לא זמינה ב-OnBackPressedCallback הדומה של AndroidX. במקרים מסוימים, כדאי להירשם לקבלת שיחה חוזרת באמצעות PRIORITY_OVERLAY.

המצב הזה רלוונטי כשעוברים מ-onKeyPreIme() והקריאה החוזרת צריכה לקבל את תנועת החזרה אחורה במקום IME פתוח. כשמפתחים IME, הוא רושם קריאות חזרה (callbacks) עם PRIORITY_DEFAULT. כדי לוודא ש-OnBackInvokedDispatcher יפנה את תנועת החזרה לאחור לשיחה החוזרת במקום ל-IME הפתוח, צריך לרשום את השיחה החוזרת ב-PRIORITY_OVERLAY.

הבעת הסכמה לתנועת החזרה החזויה

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

כדי להביע הסכמה, מגדירים את הדגל android:enableOnBackInvokedCallback לערך true בתג <application> ב-AndroidManifest.xml.

<application
    ...
    android:enableOnBackInvokedCallback="true"
    ... >
...
</application>

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

  • השבתת האנימציה החזויה של המערכת של תנועת החזרה.
  • מתעלמת מ-OnBackInvokedCallback, אבל הקריאות ל-OnBackPressedCallback ממשיכות לפעול.

הסכמה ברמת הפעילות

החל מגרסה 14 של Android, הדגל android:enableOnBackInvokedCallback מאפשר לכם להביע הסכמה לשימוש באנימציות מערכת חזויות ברמת הפעילות. התנהגוּת הזו מאפשרת להעביר בקלות רבה יותר אפליקציות גדולות עם כמה פעילויות לתנועות חזרה חזויות. ב-Android 15, התכונה 'חזרה חזויה' כבר לא עומדת מאחורי האפשרות למפתחים. אפליקציות יכולות להביע הסכמה לשימוש בחזרה חזותית לכל הפעילות או ברמת הפעילות.

הקוד הבא מציג דוגמה לשימוש ב-enableOnBackInvokedCallback כדי להפעיל את אנימציית המערכת של החזרה לבית מ-MainActivity:

<manifest ...>
    <application . . .

        android:enableOnBackInvokedCallback="false">

        <activity
            android:name=".MainActivity"
            android:enableOnBackInvokedCallback="true"
            ...
        </activity>
        <activity
            android:name=".SecondActivity"
            android:enableOnBackInvokedCallback="false"
            ...
        </activity>
    </application>
</manifest>

בדוגמה שלמעלה, הגדרה של android:enableOnBackInvokedCallback=true ל-".SecondActivity" מפעילה את האנימציה של המערכת בפעילויות שונות.

כשמשתמשים בדגל android:enableOnBackInvokedCallback, חשוב לזכור את השיקולים הבאים:

  • אם מגדירים את android:enableOnBackInvokedCallback=false, האנימציות החזויות החוזרות מושבתות ברמת הפעילות או ברמת האפליקציה, בהתאם למיקום שבו הגדרתם את התג, והמערכת מורה למערכת להתעלם מקריאות ל-API של הפלטפורמה OnBackInvokedCallback. עם זאת, הקריאות ל-OnBackPressedCallback ממשיכות לפעול כי OnBackPressedCallback תואם לאחור וקורא ל-API‏ onBackPressed, שאין תמיכה בו לפני Android 13.
  • הדגל enableOnBackInvokedCallback ברמת האפליקציה קובע את ערך ברירת המחדל לכל הפעילויות באפליקציה. כדי לשנות את ברירת המחדל לכל פעילות באפליקציה, מגדירים את הדגל ברמת הפעילות, כפי שמוצג בדוגמת הקוד הקודמת.

שיטות מומלצות לשיחות חוזרות

ריכזנו כאן כמה שיטות מומלצות לשימוש בקריאות החזרה (callbacks) הנתמכות של המערכת: BackHandler (לכתיבה), OnBackPressedCallback או OnBackInvokedCallback.

איך קובעים את מצב ממשק המשתמש שמפעיל או משבית כל קריאה חוזרת (callback)

מצב ממשק המשתמש הוא מאפיין שמתאר את ממשק המשתמש. מומלץ לפעול לפי השלבים הכלליים האלה.

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

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

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

שימוש בהחזרות קריאה (callbacks) לאחור של המערכת ללוגיקה של ממשק המשתמש

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

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

לדוגמה, אם אתם מיירטים אירועים חוזרים רק כדי לתעד ביומן, כדאי לתעד אותם במחזור החיים של Activity או Fragment.

  • עבור תרחישים של פעילות לפעילות או מקרים של מקטע לפעילות, צריך לרשום ביומן אם הערך של isFinishing בתוך onDestroy הוא true במחזור החיים של הפעילות.
  • במקרים של אירועים מ-fragment ל-fragment, מתעדים אם הערך של isRemoving ב-onDestroy הוא true במהלך מחזור החיים של תצוגת ה-Fragment. לחלופין, אפשר להשתמש בשיטות onBackStackChangeStarted או onBackStackChangeCommitted בתוך FragmentManager.OnBackStackChangedListener.

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

יצירת קריאות חזרה עם אחריות יחידה

אפשר להוסיף מספר קריאות חוזרות למפנה. הקריאות החוזרות (callback) מתווספות למקבץ שבו הקריאה החוזרת האחרונה שנוספה מטפלת בתנועת החזרה הבאה עם תנועת קריאה חוזרת אחת לכל חזרה.

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

סדר הקריאות החוזרות בערימה.
איור 2. תרשים של סטאק קריאה חוזרת.

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

הקריאה החוזרת (callback) השנייה יכולה לכלול רכיב מהותי שתומך בחיזוי חזרה, מעבר ל-AndroidX באמצעות ממשקי Progress API או קריאה חוזרת (callback) אחרת בהתאמה אישית.

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

באופן דומה, פונקציית ה-callback הפנימית של supportFragmentManager פועלת אם פונקציות ה-callback שלמעלה מושבתות והמצב של ה-stack שלה לא ריק. ההתנהגות הזו עקבית גם כשמשתמשים ב-FragmentManager וגם כשמשתמשים ב-NavigationComponent לניווט, כי NavigationComponent מסתמך על FragmentManager. בדוגמה הזו, הקריאה החוזרת הזו מופעלת אם המשתמש לא מזין טקסט בטופס, וכתוצאה מכך הקריאה החוזרת 'האם ברצונך להמשיך?' מושבתת.

לסיום, super.onBackPressed() היא קריאה חוזרת ברמת המערכת, שפועלת שוב אם הקריאות החוזרות שלמעלה מושבתות. כדי להפעיל אנימציות מערכת כמו 'חזרה הביתה', 'חוצות-פעילות' ו'ריבוי משימות', המקבץ האחורי של supportFragmentManager צריך להיות ריק, כדי שהקריאה הפנימית החוזרת תהיה מושבתת.

בדיקת האנימציה של חיזוי תנועת החזרה

אם אתם עדיין משתמשים ב-Android 13 או ב-Android 14, תוכלו לבדוק את האנימציה של החזרה הביתה, שמוצגת באיור 1.

כדי לבדוק את האנימציה, מבצעים את השלבים הבאים:

  1. במכשיר, עוברים אל הגדרות > מערכת > אפשרויות למפתחים.

  2. בוחרים באפשרות אנימציה חזרה חזוי.

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