Use case: When I open a screen, I want a textField...
# compose
s
Use case: When I open a screen, I want a textField to be focused immediately and have the keyboard show. More in thread 🧵
Currently, I am doing something like
Copy code
@Composable
fun Comp() {
  val focusRequester = remember { FocusRequester() }
  DisposableEffect(Unit) {
    focusRequester.requestFocus()
    onDispose {
      focusRequester.freeFocus() // Might not even need this since at this point I've left this screen
    }
  }
  BasicTextField(modifier = Modifier.focusRequester(focusRequester))
}
But I am getting the error of:
Copy code
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() }
I can’t find anything in the documentation regarding focus aside from just the package reference but it doesn’t help with my use case. What is the proper way to achieve this?
Hmm, using
LaunchedEffect
instead of `DisposableEffect`:
Copy code
LaunchedEffect(Unit) {
  focusRequester.requestFocus()
}
Seems to be getting the focus alright. I guess LaunchedEffect happens 1 frame after composition suceeded, while DisposableEffect happens at composition and the focusRequester modifier wasn’t called yet. And it even opened the keyboard once, but it’s not consistent about it 🤔 Plus I am getting a super weird case where I use the “back” gesture and the keyboard opens and closes instead of going back, but at this point I’m pretty sure I must be messing something up badly. Is there any sort of official documentation about handling focus that I can follow to avoid all these weird things I am doing 😂
j
I have been using LaunchedEffect as well for this. I haven’t found much in the way of official docs for this. I generally observe that the keyboard dismisses once the focused field is no longer in composition, but I have had a few times where the keyboard doesn’t dismiss after navigating to a different view. It’s inconsistent and random so I haven’t hunted down why it’s happening yet.
I originally had a call to dismiss the keyboard when I navigate away from a view that uses it, but I ran into timing issues if the next screen needed the keyboard so that ended up being worse than the rare cases where it doesn’t dismiss now. It’s something I’ll have to address before we release though
f
Copy code
@Composable
fun SearchBarComponent(
    keyboardController: SoftwareKeyboardController? = LocalSoftwareKeyboardController.current,
    onTextChanged: ((String) -> Unit)? = null,
) {
    var text by rememberSaveable { mutableStateOf("") }
    val focusRequester = remember { FocusRequester() }
    TextField(
        modifier = Modifier
            .fillMaxWidth()
            .focusRequester(focusRequester)
            .height(56.dp),
        value = text,
        onValueChange = {
            text = it
            onTextChanged?.invoke(it)
        })
    DisposableEffect(Unit) {
        focusRequester.requestFocus()
        keyboardController?.show()

        onDispose {
            focusRequester.freeFocus()
            keyboardController?.hide()
        }
    }
}
s
But Hristijan, doesn’t this come with the problem I mentioned above? By the time focusRequester.requestFocus() is called, the FocusRequester might not be initialized and requestFocus() is called during composition throwing an exception. Are you using this in your apps already?
f
Yes i use it in my app already, works perfectly so far no complaints
162 Views