Enable and focus Textfield at once in Jetpack Compose

Viewed 1832

I'm trying to implement a TextField in Jetpack Compose with the following functionality: at first it is disabled, but when a user presses the Button, it gets enabled and at the same moment receives focus. This was my approach:

var text by remember { mutableStateOf("text") }
var enabled by remember { mutableStateOf(false)}
val focusRequester = remember { FocusRequester() }

Column {
    TextField(
        value = text,
        onValueChange = { text = it },
        enabled = enabled,
        modifier = Modifier.focusRequester(focusRequester),
        textStyle = TextStyle(fontSize = 24.sp)
    )
    Button(onClick = {
        enabled = true
        focusRequester.requestFocus()
    }) {
        Text("Enable and request focus")
    }

But when the button is pressed, the TextField only gets enabled, not focused. To focus it, user has to click it once again. What am I doing wrong and what is the possible workaround?

enter image description here

3 Answers

You have to listen the change of the enabled parameter to give the focus to the TextField.

You can change your code to:

    Button(onClick = {
        enabled = true

    }) {
        Text("Enable and request focus")
    }

    DisposableEffect(enabled) {
        if (enabled){
            focusRequester.requestFocus()
        }
        onDispose {}
    }

Simply add the delay after enabling textfield like this:

var text by remember { mutableStateOf("text") }
var enabled by remember { mutableStateOf(false)}
val focusRequester = remember { FocusRequester() }
val scope = rememberCoroutineScope()

Column {
    TextField(
        value = text,
        onValueChange = { text = it },
        enabled = enabled,
        modifier = Modifier.focusRequester(focusRequester),
        textStyle = TextStyle(fontSize = 24.sp)
    )
    Button(onClick = {
        scope.launch {
            enabled = true
            delay(100)
            focusRequester.requestFocus()
        }
    }) {
        Text("Enable and request focus")
    }
}

I once had a similar issue and I solved it by using interactionSource. The code looked something like this:

var text by remember { mutableStateOf("text") }
var enabled by remember { mutableStateOf(false)}
val focusRequester = remember { FocusRequester() }
val interactionSource = remember { MutableInteractionSource() } // add this

Column {
    TextField(
        value = text,
        onValueChange = { text = it },
        enabled = enabled,
        modifier = Modifier
            .focusable(interactionSource = interactionSource) // and this
            .focusRequester(focusRequester),
        textStyle = TextStyle(fontSize = 24.sp)
    )
    ...

IIRC it was important to have .focusable() and .focusRequester() in the right order, but cannot remember which exactly, so try to swap them if it won't work immediately.

Related