При навигации по сложным пользовательским интерфейсам с помощью аппаратной клавиатуры или 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 follows the default focus order to determine which child to focuses.
Вы можете настроить, какой дочерний элемент будет получать фокус при первом входе, передав резервный 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 отключен.
- Цели фокусировки
- Порядок обхода фокуса
- Цели по группам
- Программный запрос фокуса
- Как переместить и убрать фокус