Навигация с помощью клавиши Tab и фокус клавиатуры
В Compose Multiplatform для настольных компьютеров можно настроить переход между компонентами с помощью сочетания клавиш Tab для перехода к следующему компоненту и Shift+Tab для перехода к предыдущему.
Навигация с помощью Tab по умолчанию
По умолчанию навигация с помощью клавиши Tab позволяет пользователям переходить между компонентами, доступными для получения фокуса, в порядке их отображения. Эта возможность включена по умолчанию и не требует дополнительного кода.
К компонентам, доступным для получения фокуса, относятся компоненты, в реализации которых используются модификаторы clickable(), selectable(), toggleable() или focusable(). Например, текстовые поля, кнопки, ползунки, элементы навигации, элементы управления выбором с callback, отличным от null, перегрузки Card() с onClick, Surface() и ListItem().
Ниже показано окно, в котором пользователь может перемещаться между пятью текстовыми полями с помощью стандартных сочетаний клавиш:
Пользовательские компоненты, доступные для получения фокуса
Чтобы включить в порядок навигации с помощью Tab компонент, который по умолчанию не может получить фокус, примените модификатор focusable().
Чтобы изменить внешний вид компонента при получении фокуса, передайте MutableInteractionSource модификатору focusable(), считывайте состояние фокуса с его помощью через collectIsFocusedAsState() и используйте это состояние для изменения стиля компонента: задайте другой фон, границу или любой другой способ выделения. Чтобы компонент реагировал на нажатия клавиш, обрабатывайте события клавиатуры с помощью модификатора onKeyEvent().
В следующем примере компонуемая функция Box() превращается в компонент, похожий на кнопку. Рамка выделяется при получении фокуса, а нажатие Enter или Space вызывает соответствующее действие:
Чтобы перемещать фокус не в порядке отображения компонентов, объедините два модификатора:
focusRequester() прикрепляет дескриптор FocusRequester к компоненту, доступному для получения фокуса. Если компонент по умолчанию не может получить фокус, примените модификатор focusable()послеfocusRequester().
focusProperties() задаёт элементы next и previous в порядке навигации с помощью Tab: компоненты с дескриптором FocusRequester, на которые можно перевести фокус нажатием Tab или Shift+Tab.
В следующем примере для каждого из пяти текстовых полей создаётся FocusRequester, а порядок навигации с помощью Tab по умолчанию меняется на обратный:
Чтобы перевести компонент в фокус без взаимодействия с пользователем, прикрепите FocusRequester к компоненту, доступному для получения фокуса, с помощью модификатора focusRequester() и вызовите FocusRequester.requestFocus(). Если компонент по умолчанию не может получить фокус, модификатор focusable() следует применить послеfocusRequester().
В следующем примере кнопка перемещает фокус на текстовое поле, а затем обратно на себя:
В формах и диалоговых окнах фокус часто сразу устанавливается на первое поле ввода, чтобы пользователь мог начать вводить текст, не используя мышь. В этом случае запросите фокус в блоке LaunchedEffect(Unit), который выполняется один раз после добавления компонента в композицию.
В следующем примере фокус устанавливается на первое текстовое поле сразу после открытия окна:
Перемещение фокуса из многострочных текстовых полей
В многострочных текстовых полях нажатие Tab вставляет символ табуляции вместо перемещения фокуса на следующий компонент:
Column {
repeat(5) {
TextField(
state = rememberTextFieldState("Hello, World!"),
// MultiLine is the default value of lineLimits
lineLimits = TextFieldLineLimits.MultiLine(),
modifier = Modifier.padding(8.dp)
)
}
}
Это известная проблема: CMP-5822. Она затрагивает все текстовые поля, в которых можно вводить несколько строк, что является поведением по умолчанию. В качестве обходного решения перехватывайте клавишу Tab с помощью модификатора onPreviewKeyEvent и перемещайте фокус, используя FocusManager из LocalFocusManager: