שחזור המיקוד

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

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

ב-Jetpack Compose, מאגדים שניתן לגלול בהם כמו LazyColumn,‏ LazyRow ו-LazyVerticalGrid פועלים באופן אוטומטי כקבוצות מיקוד. כדי להפעיל שחזור של המיקוד ברשימה או ברשת שנטענות באופן עצלני, מוסיפים את משנה המאפיין focusRestorer:

LazyColumn(
    modifier = Modifier.focusRestorer()
) {
    items(items) { item ->
        Button(onClick = { /* Handle click */ }) {
            Text(item)
        }
    }
}

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

החזרת המיקוד בשורה ובעמודה

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

כדי להפעיל את השחזור של המיקוד ב-Row או ב-Column, משלבים את focusGroup עם focusRestorer:

Row(
    modifier = Modifier
        .focusGroup()
        .focusRestorer()
) {
    Button(onClick = { /* Action 1 */ }) {
        Text("First item")
    }
    Button(onClick = { /* Action 2 */ }) {
        Text("Second item")
    }
    Button(onClick = { /* Action 3 */ }) {
        Text("Third item")
    }
}

ציון יעד חלופי למיקוד

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

אתם יכולים להתאים אישית את הרכיב הצאצא שמקבל את המיקוד בכניסה הראשונה על ידי העברת FocusRequester חלופי אל focusRestorer (או אל lambda שמחזיר FocusRequester בגרסאות קודמות של Compose):

val firstItemRequester = remember { FocusRequester() }

LazyColumn(
    modifier = Modifier.focusRestorer(firstItemRequester)
) {
    itemsIndexed(items) { index, item ->
        val itemModifier = if (index == 0) {
            Modifier.focusRequester(firstItemRequester)
        } else {
            Modifier
        }
        Button(
            onClick = { /* Handle click */ },
            modifier = itemModifier
        ) {
            Text(item)
        }
    }
}

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

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

כדי להעביר את המיקוד ליעד הפעיל, משלבים את Modifier.focusGroup() עם focusProperties ומגדירים את המאפיין onEnter (או enter בגרסאות קודמות של Compose):

val (homeRequester, searchRequester, settingsRequester) = remember { FocusRequester.createRefs() }

val selectedRequester = when (currentDestination) {
    "home" -> homeRequester
    "search" -> searchRequester
    "settings" -> settingsRequester
    else -> homeRequester
}

NavigationRail(
    modifier = modifier
        .focusProperties {
            // Redirect focus to the selected item when focus enters the navigation rail
            onEnter = { selectedRequester.requestFocus() }
        }
        .focusGroup()
) {
    NavigationRailItem(
        selected = currentDestination == "home",
        onClick = { onNavigate("home") },
        icon = { Icon(Icons.Default.Home, contentDescription = "Home") },
        label = { Text("Home") },
        modifier = Modifier.focusRequester(homeRequester)
    )
    NavigationRailItem(
        selected = currentDestination == "search",
        onClick = { onNavigate("search") },
        icon = { Icon(Icons.Default.Search, contentDescription = "Search") },
        label = { Text("Search") },
        modifier = Modifier.focusRequester(searchRequester)
    )
    NavigationRailItem(
        selected = currentDestination == "settings",
        onClick = { onNavigate("settings") },
        icon = { Icon(Icons.Default.Settings, contentDescription = "Settings") },
        label = { Text("Settings") },
        modifier = Modifier.focusRequester(settingsRequester)
    )
}

שחזור המיקוד במעברים בין מסכים

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

כדי לשמור ולשחזר את המיקוד במעברים בין מסכים:

  1. משייכים את מאגר התגים ל-FocusRequester.
  2. לפני שמפעילים את אירוע הניווט, קוראים ל-saveFocusedChild() ב-FocusRequester של הקונטיינר.
  3. כשהמשתמש חוזר למסך, צריך לבקש מיקוד ראשוני ב-container או להפעיל את restoreFocusedChild().