При навигации по сложному интерфейсу с помощью аппаратной клавиатуры или D-pad пользователи часто переходят между разными разделами экрана, например от боковой панели навигации к списку контента, взаимодействуют с элементом, а затем возвращаются обратно. Восстановление фокуса позволяет контейнерам запоминать дочерний элемент, на котором ранее был установлен фокус, и восстанавливать его, когда фокус возвращается в контейнер.
Восстановление фокуса в контейнерах с возможностью прокрутки
В 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") } }
Как указать резервную цель фокусировки
Когда фокус впервые попадает в контейнер, ранее выделенного дочернего элемента нет. При определении того, на каком дочернем элементе нужно сфокусироваться, функция Compose следует порядку фокусировки по умолчанию.
Вы можете настроить, какой дочерний элемент получит фокус при первом входе, передав резервное объявление FocusRequester в focusRestorer (или лямбда-функцию, возвращающую 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) ) }
Восстановление фокуса при переходе между экранами
Когда пользователь нажимает на элемент, чтобы перейти на экран сведений, а затем возвращается назад с помощью кнопки или жеста, вы можете восстановить фокус на элементе, на который он нажал.
Чтобы сохранять и восстанавливать фокус при переходе между экранами:
- Свяжите контейнер с
FocusRequester. - Перед тем как активировать событие перехода, вызовите
saveFocusedChild()дляFocusRequesterконтейнера. - Когда пользователь возвращается на экран, запросите начальную фокусировку на контейнере или вызовите
restoreFocusedChild().
Рекомендуем
- Примечание. Текст ссылки показывается, когда JavaScript отключен.
- Цели фокусировки
- Порядок перехода фокуса
- Как сгруппировать цели
- Как запросить фокус программным способом
- Перемещение и снятие фокуса