Home > Blockchain >  How to handle key events during TextField editing in Compose?
How to handle key events during TextField editing in Compose?

Time:11-25

I'm making a chess engine on desktop compose, one of the things I'm trying to implement is a TextField where i can paste in several moves to recreate games.

I'm having problems saving the text that I input into my TextField composable.

My text composable is as follows, I understand that with my current implementation it prints every time the move variable changes, but i just wanted this to happen when I press the ENTER key on my keyboard.

I'm using the print to try some code but what i want to do is to save the String to a list or something, but that i can implement in my own later.

I only find explanations on how to do it with android and android specific methods.

Text("   Play", textAlign = TextAlign.Center, fontSize = 30.sp)
val move = remember { mutableStateOf("Play") }
TextField(
    value = move.value,
    onValueChange = { move.value = it },
    label = { Text("Move") },
    maxLines = 1,
    textStyle = TextStyle(color = Color.Black, fontWeight = FontWeight.Bold),
    modifier = Modifier.padding(20.dp)
)
println(move.value)

It has been pointed out to me a solution to handle the ENTER keybind as been answered here: How to trigger PC Keyboard inputs in Kotlin Desktop Compose I'm just having some issues, that I press ENTER unable to handle the String when I press ENTER it prints continuosly isntead of only once based on my research I need to implement something like this: Box doesn't capture key events in Compose Desktop but i can't seem to be able to use the KeyEvent.ACTION_UP not sure if it's specific to the editText, if I'm missing some imports, or if there's another way to do it with the TextField composable.

My code after the given suggestions

val requester = remember { FocusRequester() }
LaunchedEffect(Unit) {
    requester.requestFocus()
}
Text("   Play", textAlign = TextAlign.Center, fontSize = 30.sp)
val move = remember { mutableStateOf("Play") }
TextField(
    value = move.value,
    onValueChange = { move.value = it },
    label = { Text("Move") },
    maxLines = 1,
    textStyle = TextStyle(color = Color.Black, fontWeight = FontWeight.Bold),
    modifier = Modifier.padding(20.dp)
        .onKeyEvent {
    //if(keyCode==KeyEvent.KEYCODE_ENTER&&event.action==KeyEvent.ACTION_UP){
            if (it.key == Key.Enter) {
                println(move.value)
                true
            } else {
                // let other handlers receive this event
                false
            }
        }
        .focusRequester(requester)
        .focusable()
)

I managed to fix this problem by changing the if condition to this:

if (it.key == Key.Enter && move.value!="") {
    println(move.value)
    move.value = ""
    true
}

So that everytime I write something and press ENTER it prints the String and clears the mutableState, and while ENTER is still pressed it won't print because the mutableState is an empty String. I'm still looking for a better solution than this

CodePudding user response:

You can capture key events with Modifier.onKeyEvent. With the text field you don't need any focus capturing, because it's already there. If you would need to do the same for a custom view, check out this answer

To check which button was pressed you can use key, and to check where it was released, you can check type:

TextField(
    value = text,
    onValueChange = { text = it },
    modifier = Modifier
        .onKeyEvent { keyEvent ->
            if (keyEvent.key != Key.Enter) return@onKeyEvent false
            if (keyEvent.type == KeyEventType.KeyUp) {
                println("Enter released")
            }
            true
        }
)
  • Related