How to Clear Textfield Focus When Closing the Keyboard and Prevent Two Back Presses Needed to Exit App in Jetpack Compose

How to clear TextField focus when closing the keyboard and prevent two back presses needed to exit app in Jetpack Compose?

There's a compose issue with focused text field prevents back button from dismissing the app when keyboard is hidden. It's marked as fixed, but will be included in some future release, not in 1.0

But, as I understand, the fact that text field is not loosing focus after keyboard being dismissed, is intended behaviour on Android(because of possible connected keyboard? I didn't get the reason). And this is how it works in old android layout too

It seems strange to me, so I came with the following modifier which resigns focus when keyboard disappears:

fun Modifier.clearFocusOnKeyboardDismiss(): Modifier = composed {
var isFocused by remember { mutableStateOf(false) }
var keyboardAppearedSinceLastFocused by remember { mutableStateOf(false) }
if (isFocused) {
val imeIsVisible = WindowInsets.isImeVisible
val focusManager = LocalFocusManager.current
LaunchedEffect(imeIsVisible) {
if (imeIsVisible) {
keyboardAppearedSinceLastFocused = true
} else if (keyboardAppearedSinceLastFocused) {
focusManager.clearFocus()
}
}
}
onFocusEvent {
if (isFocused != it.isFocused) {
isFocused = it.isFocused
if (isFocused) {
keyboardAppearedSinceLastFocused = false
}
}
}
}

Usage:

BasicTextField(
value = valueState.value,
onValueChange = {
valueState.value = it
},
modifier = Modifier
.clearFocusOnKeyboardDismiss()
)

How clear focus for BasicTextField in Jetpack Compose?

To clear focus from the currently focused component you can use the FocusManager.clearFocus method:

    val focusRequester = remember { FocusRequester() }
val focusManager = LocalFocusManager.current
var value by rememberSaveable { mutableStateOf("initial value") }
BasicTextField(
value = value,
onValueChange = { value = it },
decorationBox = { innerTextField ->
Row(
Modifier
.background(Color.LightGray, RoundedCornerShape(percent = 30))
.padding(16.dp)
.focusRequester(focusRequester)
) {
//...
innerTextField()
}
}
)

Button(onClick = { focusManager.clearFocus() }) {
Text("Clear focus")
}

android compose textfield how to dismiss keyboard on touch outside

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.

Jetpack compose soft keyboard opens up when switching apps

This was a bug in compose (https://issuetracker.google.com/issues/225541817). It's fixed as of compose 1.2.0-beta02

How to close the virtual keyboard from a Jetpack Compose TextField?

Starting from compose 1.0.0-alpha12 (and still valid in compose 1.3.1) the onImeActionPerformed is deprecated and suggested approach is to use keyboardActions with combination of keyboardOptions:

    val focusManager = LocalFocusManager.current

OutlinedTextField(
value = ...,
onValueChange = ...,
label = ...,
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
keyboardOptions = KeyboardOptions.Default.copy(imeAction = ImeAction.Done, keyboardType = KeyboardType.Password),
)

focusManager.clearFocus() will take care of dismissing the soft keyboard.



Related Topics



Leave a reply



Submit