Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

android compose textfield how to dismiss keyboard on touch outside

Here is a Row that contains a TextField in a full-screen column. onFocusChanged callback is called when tapping the TextField (going Active) and when the Done button is pressed in the keyboard. But the handler is not called I tap outside the TextField. So I am not able to close the keyboard. Any idea?

val (nameText, setNameText) = remember { mutableStateOf("")}
val keyboardController = LocalSoftwareKeyboardController.current
val focusRequester = FocusRequester()

Column(
    modifier = Modifier
        .fillMaxWidth()
        .fillMaxHeight()
        .padding(10.dp)
) { 
    Row(
        modifier = Modifier
            .fillMaxWidth(),
        horizontalArrangement = Arrangement.SpaceAround
    ) {
        TextField(
            value = nameText,
            onValueChange = setNameText,
            modifier = Modifier
                .focusRequester(focusRequester)
                .onFocusChanged {
                    if (!it.isFocused) {
                        keyboardController?.hide()
                    }
                }
                .padding(horizontal = 0.dp, vertical = 0.dp)
                .height(50.dp)
                .fillMaxWidth(),
            KeyboardOptions(
                keyboardType = KeyboardType.Text,
                imeAction = androidx.compose.ui.text.input.ImeAction.Done
            ),
            keyboardActions = KeyboardActions(onDone = {
                localFocusManager.clearFocus()
            }),
            placeholder = { Text("Enter a name", fontSize = 14.sp) }
        )
    }
}

I tried setting a focus handler in Column but did not work (focus handler not called when tapping outside). Using compose version 1.0.2.

like image 385
rysv Avatar asked Sep 09 '25 18:09

rysv


1 Answers

If you want to remove focus on tap, you can add pointerInput modifier with detectTapGestures to your Column:

Column(
    modifier = Modifier
        .fillMaxWidth()
        .fillMaxHeight()
        .padding(10.dp)
        .pointerInput(Unit) {
            detectTapGestures(onTap = {
                localFocusManager.clearFocus()
            })
        }
)

I add it after the padding modifier, so the padding view part won't receive touches. If you change the order, padding will be included in the clickable part.

Look at other gestures if tap is not enough for you.

like image 200
Philip Dukhov Avatar answered Sep 12 '25 07:09

Philip Dukhov