Jetpack Compose - Capture Key Event In Text Field
Asked Answered
V

3

11

I want to create a text field inside a todo list where when the user presses backspace on an empty text field , it removes itself from the list , very simple to do as you can see !

Jetpack Compose , Core Text Field does not propogate its key events to parent composables / modifiers if the key event is editable ~~ written in their code

so I tried this and it does not work as expected

Modifier.onKeyEvent {
     Log.d("BL_KeyEvent",it.type.toString())
     if (it.key.keyCode == Key.Backspace.keyCode) {
           if (item.text.isEmpty()) {
              onBackspaceRemove()
           }
       }
       false
     }

I am just wondering how I could achieve it , since CoreTextField is internal and I have no way to capture key event in a text fielld

Vaudois answered 20/8, 2021 at 11:55 Comment(1)
I need the onBackspaceRemove() methodSwartz
M
8

Unsue if this has been fixed since you last tried @Waqas Tahir but I'm using ComposeUI v1.0.2 the following works for me:

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun aTextFieldWithOnBackspacePressedAction() {
    // this should be hoisted to ViewModel
    var text by remember { mutableStateOf("") }

    BasicTextField(
        value = text,
        // this also should be hoisted to ViewModel
        onValueChange = { text = it },
        modifier = Modifier
            .onKeyEvent { event: KeyEvent ->
                // handle backspace key
                if (event.type == KeyEventType.KeyUp &&
                    event.key == Key.Backspace &&
                    text.isEmpty()
                // also any additional checks of the "list" i.e isNotEmpty()
                ) {
                    // TODO remove from list
                    return@onKeyEvent true
                }
                false
            }
    )
}
Monosymmetric answered 14/10, 2021 at 15:28 Comment(1)
It has indeed been fixed , I tried it !Vaudois
S
1

@Composable
fun StackList(){
    var list = remember { mutableStateListOf<String>() } // This should be in your viewmodel
    LazyColumn{
        items(list){item ->
            var value by remember { mutableStateOf("") }
            TextField(
                modifier = Modifier.onKeyEvent {
                    Log.d("BL_KeyEvent",it.type.toString())
                    if (it.key.keyCode == Key.Backspace.keyCode) {
                        if (value.isEmpty()) {
                            list.remove(item)
                        }
                    }
                    false
                },
                value = value,
                onValueChange = {value = it}
            )
        }
    }
}
Swartz answered 20/8, 2021 at 12:58 Comment(3)
As I've already said , the event is not being fired when I press backspace , and I am using the same code you have written because of core text field using the onKeyEvent and returning true when editable so it won't propogate up in the composable heirarchyVaudois
@WaqasTahir Im using basic text field and its workingVictual
A popular answer on stackoverflow states you can't intercept direct key-presses from the soft keyboard. It is possible to intercept keys from an externally attached board as stated here, but apparently, your use case requires a custom keyboard to be made. It is not hard to do, so give it a shot.Swartz
B
0

Just change false to true. It should work.

Bonzer answered 13/12, 2021 at 23:49 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Enlighten

© 2022 - 2024 — McMap. All rights reserved.