onKeyEvent Modifier doesn't work in Jetpack Compose
Asked Answered
F

2

13
return ComposeView(requireContext()).apply {
    setContent {
        Box(
            Modifier
                .onKeyEvent {
                    if (it.isCtrlPressed && it.key == Key.A) {
                        println("Ctrl + A is pressed")
                        true
                    } else {
                        false
                    }
                }
                .focusable()
        )
    }
}

Why the key event cannot be called in fragment while using hardware keyboard of tablet?

Filiform answered 20/8, 2021 at 11:2 Comment(0)
M
15

As documentation of onKeyEvent says:

will allow it to intercept hardware key events when it (or one of its children) is focused.

Which means you need to make your box focused, not just focusable. To do this you need a FocusRequester, in my example I'm asking focus when view renders. Check out more in this article

For the future note, that if user taps on a text field, your box will loose focus, but onKeyEvent still gonna work if this txt field is inside the box

Looks like empty box cannot become focused, so you need to add some size with a modifier. It still will be invisible:

val requester = remember { FocusRequester() }
Box(
    Modifier
        .onKeyEvent {
            if (it.isCtrlPressed && it.key == Key.A) {
                println("Ctrl + A is pressed")
                true
            } else {
                false
            }
        }
        .focusRequester(requester)
        .focusable()
        .size(10.dp)
)
LaunchedEffect(Unit) {
    requester.requestFocus()
}

Alternatively just add content to Box so it will stretch and .size modifier won't be needed anymore

This code works fine with my Bluetooth keyboard + android smartphone, emulator seems not recognizing CTRL

Marsland answered 20/8, 2021 at 14:38 Comment(1)
I used this approach to activate keyboard events within LazyVerticalGrid that contains several buttons. The only thing that ENTER key press was not handled because first control within the content was always getting focus. To avoid that I used following code: LaunchedEffect(Unit) { focusRequester.requestFocus() focusRequester.freeFocus() focusRequester.captureFocus() }Knickerbocker
K
0

If you are using androidx.compose.material3.OutlinedTextField then you can use KeyboardActions instead:

keyboardActions = KeyboardActions(onDone = { /* Do something */ })
Kassie answered 13/3, 2023 at 13:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.