https://kotlinlang.org logo
Title
s

Stylianos Gakis

02/01/2022, 4:23 PM
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
@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:
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`:
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

Joseph Hawkes-Cates

02/01/2022, 4:33 PM
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

FunkyMuse

02/01/2022, 7:36 PM
@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

Stylianos Gakis

02/02/2022, 9:08 AM
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

FunkyMuse

02/02/2022, 11:52 AM
Yes i use it in my app already, works perfectly so far no complaints