2

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!

Jonathan
  • 21
  • 2

0 Answers0