לספק אפשרויות ניווט מותאמות אישית חזרה

המשתמשים יכולים לנווט אחורה בין המסכים באמצעות ניווט אחורה. ברוב מכשירי Android יש הכפתור "הקודם" – פיזי, מבוסס תוכנה או מבוסס תנועה. בדרך כלל, לא מומלץ להוסיף לאפליקציה את הכפתור "הקודם". עם זאת, במכשירי Android Automotive OS ‏ (AAOS) במצב תאימות יש לחצן "הקודם" של המערכת. הוא מטפל בניווט, כך שלא צריך להוסיף ניווט משלכם. מידע נוסף מופיע במאמר בנושא מצב תאימות של AAOS.

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

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

ב-Jetpack פיתוח נייטיב, אפשר לטפל בניווט מותאם אישית אחורה באמצעות ה-composable‏ BackHandler.

כשמשתמשים ב-Navigation Compose, בדרך כלל משתמשים ב-NavController.navigateUp() או ב-NavController.popBackStack() כדי לנווט למסך הקודם במקבץ פעילויות קודמות (back stack). עם זאת, BackHandler שימושי במקרים שבהם רוצים להטמיע התנהגות מותאמת אישית כשהמשתמש לוחץ על הכפתור "הקודם" של המערכת או משתמש בתנועת החזרה. לדוגמה, אם אתם מציגים WebView באפליקציה, יכול להיות שתרצו לאפשר למשתמשים לנווט חזרה דרך היסטוריית הגלישה כשהם לוחצים על הכפתור "הקודם" של המערכת.

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

הטמעה של ניווט אחורה בהתאמה אישית באמצעות Views

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

המאפיין OnBackPressedDispatcher קובע איך אירועים של הכפתור "הקודם" נשלחים לאובייקט OnBackPressedCallback אחד או יותר. ה-constructor של OnBackPressedCallback מקבל ערך בוליאני למצב ההפעלה הראשוני. רק אם מופעלת קריאה חוזרת (callback), למשל אם הפונקציה isEnabled() מחזירה את הערך true, הפונקציה handleOnBackPressed() של הקריאה החוזרת נקראת על ידי הפונקציה dispatcher כדי לטפל באירוע של הכפתור "הקודם". אפשר לשנות את המצב המופעל באמצעות קריאה ל-setEnabled().

מוסיפים קריאות חוזרות באמצעות השיטות addCallback. משתמשים בשיטה addCallback() שמקבלת LifecycleOwner. כך התג OnBackPressedCallback יתווסף רק כשהתג LifecycleOwner הוא Lifecycle.State.STARTED. בנוסף, הפעילות מסירה קריאות חוזרות רשומות כשה-LifecycleOwner המשויך מושמד, וכך מונעת דליפות זיכרון. לכן, היא מתאימה לשימוש בפרגמנטים או בבעלים אחרים של מחזור חיים שיש להם משך חיים קצר יותר מהפעילות.

דוגמה להטמעה של קריאה חוזרת (callback):

Kotlin

class MyFragment : Fragment() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // This callback will only be called when MyFragment is at least Started.
        val callback = requireActivity().onBackPressedDispatcher.addCallback(this) {
            // Handle the back button event
        }

        // The callback can be enabled or disabled here or in the lambda
    }
    ...
}

Java

public class MyFragment extends Fragment {

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // This callback will only be called when MyFragment is at least Started.
        OnBackPressedCallback callback = new OnBackPressedCallback(true /* enabled by default */) {
            @Override
            public void handleOnBackPressed() {
                // Handle the back button event
            }
        };
        requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);

        // The callback can be enabled or disabled here or in handleOnBackPressed()
    }
    ...
}

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

הקריאות החוזרות פועלות לפי דפוס שרשרת האחריות. כל קריאה חוזרת בשרשרת מופעלת רק אם הקריאה החוזרת הקודמת לא הופעלה. כלומר, בדוגמה הקודמת, הקריאה החוזרת two תופעל רק אם הקריאה החוזרת three לא הופעלה. הקריאה החוזרת one תופעל רק אם הקריאה החוזרת two לא הופעלה, וכן הלאה.

שימו לב: כשמוסיפים את ה-callback באמצעות addCallback(), הוא לא מתווסף לשרשרת האחריות עד ש-LifecycleOwner עובר למצב Lifecycle.State.STARTED.

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

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