המשתמשים מנווטים אחורה בין המסכים באמצעות ניווט לאחור. לרוב מכשירי Android יש כפתור חזרה (פיזי, תוכנה או מבוסס מחוות). בדרך כלל, לא מומלץ להוסיף לאפליקציה לחצן 'הקודם'. עם זאת, במכשירי Android Automotive OS (AAOS) במצב תאימות יש לחצן 'הקודם' של המערכת. הוא מטפל בניווט, כך שלא צריך להוסיף ניווט משלכם. פרטים נוספים מופיעים במאמר בנושא מצב תאימות של AAOS.
מערכת Android שומרת מקבץ פעילויות קודמות (back stack) של יעדים כשהמשתמש מנווט באפליקציה. בדרך כלל, זה מאפשר ל-Android לנווט בצורה תקינה ליעדים קודמים כשלוחצים על הכפתור "הקודם". עם זאת, יש כמה מקרים שבהם יכול להיות שתצטרכו להטמיע באפליקציה התנהגות משלה לפעולת החזרה, כדי לספק את חוויית המשתמש הטובה ביותר. לדוגמה, כשמשתמשים ב-WebView, יכול להיות שתרצו לשנות את התנהגות ברירת המחדל של הכפתור "הקודם" כדי לאפשר למשתמש לנווט חזרה בהיסטוריית הגלישה שלו בדפדפן האינטרנט במקום במסכים הקודמים באפליקציה.
הטמעה של ניווט לאחור בהתאמה אישית ב-Compose
ב-Jetpack Compose, אתם יכולים לטפל בניווט לאחור בהתאמה אישית באמצעות הרכיב הניתן לקישור BackHandler.
כשמשתמשים ב-Navigation Compose, בדרך כלל משתמשים ב-NavController.navigateUp() או ב-NavController.popBackStack() כדי לנווט למסך הקודם במחסנית החזרה. עם זאת, BackHandler שימושי במקרים שבהם רוצים להטמיע התנהגות מותאמת אישית כשהמשתמש לוחץ על הכפתור "הקודם" של המערכת או משתמש בתנועת החזרה. לדוגמה, אם אתם מציגים WebView באפליקציה, יכול להיות שתרצו לאפשר למשתמשים לנווט חזרה באמצעות היסטוריית הגלישה כשהם לוחצים על הכפתור "הקודם" של המערכת.
שימוש בסיסי
הדוגמה הבאה מראה איך ליירט את אירוע החזרה כדי לשלוט במצב מותאם אישית (כמו כיווץ חלונית):
@Composable fun MyScreen() { var isExpanded by remember { mutableStateOf(false) } // Intercept the back button or gesture only when isExpanded is true BackHandler(enabled = isExpanded) { // Collapsing the content disables this handler, so it does not // receive the next back event. isExpanded = false } if (isExpanded) { Text("Expanded content. Go back to collapse it.") } else { Button(onClick = { isExpanded = true }) { Text("Expand") } } }
יירוט עץ קומפוזבילי
אם יש לכם כמה רכיבים קומפוזביליים מופעלים BackHandler ברמות שונות בעץ הרכיבים הקומפוזביליים, רק הרכיב הפנימי ביותר מיירט את אירוע החזרה.
הטמעה של ניווט לאחור בהתאמה אישית באמצעות תצוגות
ComponentActivity, מחלקת הבסיס של FragmentActivity ושל AppCompatActivity, מאפשרת לכם לשלוט בהתנהגות של הכפתור "הקודם" באמצעות OnBackPressedDispatcher, שאפשר לאחזר באמצעות קריאה ל-getOnBackPressedDispatcher().
ה-OnBackPressedDispatcher קובע איך אירועים של הכפתור "הקודם" נשלחים לאובייקט אחד או יותר של OnBackPressedCallback. ה-constructor של
OnBackPressedCallback מקבל ערך בוליאני למצב ההפעלה הראשוני. רק אם מופעלת קריאה חוזרת, למשל אם הפונקציה isEnabled() מחזירה את הערך true, רכיב השליחה יקרא לפונקציה handleOnBackPressed() של הקריאה החוזרת כדי לטפל באירוע של הכפתור "הקודם". כדי לשנות את מצב ההפעלה, אפשר להפעיל את setEnabled().
הוספת קריאות חוזרות מתבצעת באמצעות השיטות addCallback. משתמשים ב-method addCallback() שמקבלת LifecycleOwner. כך, הערך OnBackPressedCallback מתווסף רק כשהערך של LifecycleOwner הוא Lifecycle.State.STARTED. בנוסף, הפעילות מסירה קריאות חוזרות (callback) רשומות כשה-LifecycleOwner המשויך שלהן נהרס, וכך מונעת דליפות זיכרון. לכן, היא מתאימה לשימוש ב-fragments או בבעלים אחרים של מחזור חיים שיש להם משך חיים קצר יותר מהפעילות.
דוגמה להטמעה של קריאה חוזרת (callback):
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 } ... }
אפשר לספק כמה פונקציות קריאה חוזרת באמצעות addCallback().
כשעושים את זה, הקריאות החוזרות מופעלות בסדר הפוך לזה שבו הן נוספו – הקריאה החוזרת שנוספה אחרונה היא הראשונה שמקבלת הזדמנות לטפל באירוע של הכפתור "הקודם". לדוגמה, אם הוספתם שלוש פונקציות קריאה חוזרת (callback) בשמות one, two ו-three לפי הסדר, הן יופעלו בסדר three, two ו-one, בהתאמה.
הקריאות החוזרות פועלות לפי התבנית Chain of Responsibility. כל קריאה חוזרת בשרשרת מופעלת רק אם הקריאה החוזרת הקודמת לא הופעלה. כלומר, בדוגמה הקודמת, הקריאה החוזרת (callback) two תופעל רק אם הקריאה החוזרת (callback) three לא הופעלה. הקריאה החוזרת one תופעל רק אם הקריאה החוזרת two לא הופעלה, והדפוס הזה ממשיך לכל קריאה חוזרת נוספת.
שימו לב שכאשר מוסיפים באמצעות addCallback(), הקריאה החוזרת לא מתווספת לשרשרת האחריות עד שה-LifecycleOwner נכנס למצב Lifecycle.State.STARTED.
מומלץ מאוד לשנות את מצב ההפעלה של הקריאה החוזרת (callback) כשמדובר בשינויים זמניים, כי כך נשמר הסדר שתואר קודם. זה חשוב במיוחד אם יש קריאות חוזרות (callbacks) שרשומות בכמה בעלי מחזור חיים שונים בתצוגת עץ.
כדי להסיר את בקשת השיחה החוזרת לגמרי, צריך להתקשר אל remove().
בדרך כלל אין צורך בכך כי פונקציות ה-callback מוסרות באופן אוטומטי כשה-LifecycleOwner שמשויך אליהן נהרס.