Request Focus on TextField in jetpack compose

67.1k views Asked by At

How to auto focus on textfield in jetpack compose. When i click on textfield and start typing on it. Meantime when i click back button,then when i'm try to click on textfield, nothing happens.

val textState = remember { mutableStateOf(TextFieldValue()) }
TextField(
    modifier = Modifier.fillMaxWidth(),
    value = textState.value,
    onValueChange = { value : TextFieldValue ->
        textState.value = value
    }
)
7

There are 7 answers

0
2jan222 On

Taken from Compose Unit Tests and applied to TextField Link

    @ExperimentalFocus
    @Composable
    fun AutoFocusingText() {
        val textState = remember { mutableStateOf(TextFieldValue()) }
        val focusState = remember { mutableStateOf(FocusState.Inactive) }
        val focusRequester = FocusRequester()
        val focusModifier = Modifier.focus()
        Row(
            modifier = Modifier.focusObserver { focusState.value = it }
        ) {
            val focusRequesterModifier = Modifier.focusRequester(focusRequester)
            TextField(
                modifier = focusModifier.then(focusRequesterModifier),
                value = textState.value,
                onValueChange = { value: TextFieldValue ->
                    textState.value = value
                },

                )
        }
        onActive {
            focusRequester.requestFocus()
        }
    }

Edit: Changed Box to Row because Box has been deprecated in '1.0.0-alpha04'

4
thetaprime On

In the latest version of Jetpack Compose (1.3.3 for now), if you use this:

LaunchedEffect(Unit) {
    focusRequester.requestFocus()
}

trying to auto focus a TextField, you would get:

java.lang.IllegalStateException:
FocusRequester is not initialized. Here are some possible fixes:

    1. Remember the FocusRequester: val focusRequester = remember { FocusRequester() }
    2. Did you forget to add a Modifier.focusRequester() ?
    3. Are you attempting to request focus during composition? Focus requests should be made in
    response to some event. Eg Modifier.clickable { focusRequester.requestFocus() }

Here is an elegant solution without using delay:

val focusRequester = remember { FocusRequester() }
var textFieldLoaded by remember { mutableStateOf(false) }

TextField(
    modifier = Modifier
        .focusRequester(focusRequester)
        .onGloballyPositioned {
            if (!textFieldLoaded) {
                focusRequester.requestFocus() // IMPORTANT
                textFieldLoaded = true // stop cyclic recompositions
            }
        },
    value = someValue,
    onValueChange = {
        // ...
    }
)

// We don't need this
// LaunchedEffect(Unit) {
//     focusRequester.requestFocus()
// }

2
toutoumu On
val focusRequester = remember { FocusRequester() }
val inputService = LocalTextInputService.current
val focus = remember { mutableStateOf(false) }
BasicTextField(
    value = "value",
    modifier = Modifier
        .height(40.dp)
        .fillMaxWidth()
        .focusRequester(focusRequester)
        .onFocusChanged {
            if (focus.value != it.isFocused) {
                focus.value = it.isFocused
                if (!it.isFocused) {
                    inputService?.hideSoftwareKeyboard()
                }
            }
        },
),

LaunchedEffect("") {
    delay(300)
    inputService?.showSoftwareKeyboard()
    focusRequester.requestFocus()
}
7
Ralston On

Posting an updated Answer to the question (APIs were renamed in Compose Beta)

@Composable
fun AutoFocusingText() {
    var value by mutableStateOf("Enter Text")
    val focusRequester = remember { FocusRequester() }
    TextField(
        value = value, 
        onValueChange = { value = it },
        modifier = Modifier.focusRequester(focusRequester)
    )
    
    LaunchedEffect(Unit) {
        focusRequester.requestFocus()
    }
}
7
Gabriele Mariotti On

You can use the FocusRequester with a SideEffect.
Something like:

var text by remember { mutableStateOf("text") }

// initialize focus reference to be able to request focus programmatically
val focusRequester = FocusRequester()

Column {
    TextField(
        value = text,
        onValueChange = {
            text = it
        },
        label = { Text("label") },
        modifier = Modifier
            // add focusRequester modifier 
            .focusRequester(focusRequester)
    )

Then use focusRequester.requestFocus(). In this way the system grants focus to the component associated with this FocusRequester.

To have the field automatically focused when the screen appears you can use:

LaunchedEffect(Unit) {
    focusRequester.requestFocus()
}

To manually grant the focus to the field:

    Button(
         onClick = { focusRequester.requestFocus() }
    ){
        Text("Click to give the focus")
    }
0
Benyam On

If you wanted your text field to be focused automatically when you navigate to the screen, you can use this. This allows you not to requestFocus during composition which is not something you should do. Otherwise, you will get IllegalStateException with the message "FocusRequester is not initialized" at times.

 @Composable fun YourComposable(){ 
   val focusRequester = remember {FocusRequester()}
    
        LaunchedEffect(Unit) {
            this.coroutineContext.job.invokeOnCompletion {
                focusRequester.requestFocus()
            }
        }
    
       OutlinedTextField( modifier = Modifier.focusRequester(focusRequester))
         
              
}

This is due to the coroutine inside LaucnhedEffeect will be canceled when the LaunchedEffect leaves the composition.

1
dobhareach On

    @Composable fun SomeComposable() {
        val focusRequester = remember { FocusRequester() }

    OutlinedTextField(
        value = TextFieldValue(
        text = state.text, // state come from else where
        selection = TextRange(state.text.length,state.text.length)),  
   
        onValueChange = { _:TextFieldValue -> Unit },
        modifier = Modifier
          .fillMaxWidth()
          .focusRequester(focusRequester),)

    SideEffect {
        focusRequester.requestFocus()
        }
    }

Why SideEffect: the very first line of the docs.
For the Cursor Position this answer helped. onValueChanged is left as is in my working code, I have no need for it.