I am building a data-entry application in Jetpack Compose that is intended to be used on a device with a physical keypad. In the traditional view system, Android's built-in focus traversal works in such a way where, for example, pressing the right D-pad button when the cursor is at the end of an EditText
will change the focus to the next focusable view to the right.
default behavior using traditional views
In Jetpack Compose, however, the focus becomes trapped within a TextField
with no way to traverse to other focusable components using the D-pad.
default behavior using Compose
The only solution I'm aware of is to add an onKeyEvent
modifier to the EditText
to manually traverse the focus when key events are fired.
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun Fields() {
val focusManager = LocalFocusManager.current
Row {
TextField(
value = "foo",
onValueChange = { Unit },
modifier = Modifier.onKeyEvent {
if (it.type == KeyEventType.KeyUp && it.key == Key.DirectionRight) {
focusManager.moveFocus(FocusDirection.Right)
return@onKeyEvent true
}
return@onKeyEvent false
}
)
TextField(value = "bar", onValueChange = { Unit })
}
}
This solution works, but seems inelegant. It is also not quite optimal because there's a noticeable delay: it seems that TextField
tries to process text input before handing key events.
Does anybody know whether there's a "proper" way of handling focus with TextField
, or am I just stuck intercepting key events for now? Thanks in advance!