How to call keypress event programmatically for TextField using jetpack compose, android?

1.3k views Asked by At

When user type in TextField it will call onValueChange{} callback. but when we set the value in TextField the onValueChange{} callback will not call.

I found https://issuetracker.google.com/issues/172239032 open issue.

Below is a code snippet where I have defined TextField.

OutlinedTextField(
        value = enteredValues[index],
        onValueChange = { value: String ->
            onTextFieldValueChange(value)
        },
        singleLine = true,
        keyboardOptions = keyboardOption,
        colors = textFieldColors,
    )

To get the callback of onValueChange I want to call the keypress event programmatically so might be I will get onValueChange callback. Can anyone give me a solution? how to use keypress programmatically in jetpack compose?

1

There are 1 answers

1
nglauber On

I have no idea why you want to do this, but here it is a suggestion/workaround...

You can simulate the key event like below (credit for this answer):

fun simulateKeyPress(context: Context, key: Int) {
    val a = context as Activity
    a.window.decorView.rootView
    val inputConnection = BaseInputConnection(
        a.window.decorView.rootView,
        true
    )
    val downEvent = KeyEvent(KeyEvent.ACTION_DOWN, key)
    val upEvent = KeyEvent(KeyEvent.ACTION_UP, key)
    inputConnection.sendKeyEvent(downEvent)
    inputConnection.sendKeyEvent(upEvent)
}

Then, you can call this function passing the key code you want to send...

@Composable
fun SimulateKeySender() {
    var text by remember {
        mutableStateOf("")
    }
    val context = LocalContext.current
    val focusRequester = remember {
        FocusRequester()
    }
    Column {
        Button(
            onClick = { simulateKeyPress(context, KeyEvent.KEYCODE_A) }
        ) {
            Text(text = "Send A")
        }
        TextField(
            value = text,
            onValueChange = { text = it },
            modifier = Modifier.focusRequester(focusRequester)
        )
    }
    LaunchedEffect(Unit) {
        focusRequester.requestFocus()
    }
}

Notice that will only work if the TextField has focus, this is why I'm using the FocusRequester.