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

AndroidKotlinAndroid Jetpack-ComposeAndroid Input-MethodAndroid Compose-Textfield

Android Problem Overview


I'm using the Jetpack Compose TextField and I want to close the virtual keyboard when the user press the the action button (imeActionPerformed parameter).

val text = +state { "" }
TextField(
    value = text.value,
    keyboardType = KeyboardType.Text,
    imeAction = ImeAction.Done,
    onImeActionPerformed = { 
        // TODO Close the virtual keyboard here <<<
    }
    onValueChange = { s -> text.value = s }
)

Android Solutions


Solution 1 - Android

You can use the LocalSoftwareKeyboardController class to control the current software keyboard and then use the hide method:

var text by remember { mutableStateOf(TextFieldValue("Text")) }
val keyboardController = LocalSoftwareKeyboardController.current

TextField(
        value = text,
        onValueChange = {
            text = it
        },
        label = { Text("Label") },
        keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
        keyboardActions = KeyboardActions(
                onDone = {keyboardController?.hide()})
)

This solution closes the keyboard without removing the focus from the current TextField.

Just to highlight the difference with:

val focusManager = LocalFocusManager.current
focusManager.clearFocus()

This code closes the keyboard removing the focus from the TextField.

Solution 2 - Android

Starting from compose 1.0.0-alpha12 (and still valid in compose 1.1.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.

Solution 3 - Android

In 1.0.0 you can either use SoftwareKeyboardController or FocusManager to do this.

This answer focuses on their differences.


Setup:

var text by remember { mutableStateOf("")}

TextField(
    value = text,
    onValueChange = { text = it },
    keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
    keyboardActions = KeyboardActions(onDone = { /* TODO */ }),
)

setup


SoftwareKeyboardController:

Based on @Gabriele Mariottis answer.

val keyboardController = LocalSoftwareKeyboardController.current

// TODO =
keyboardController?.hide()

This only closes the keyboard, but does NOT clear the focus from any focused TextField (note the cursor & thick underline).

Using Keyboard Controller


FocusManager:

Based on @azizbekians answer.

val focusManager = LocalFocusManager.current

// TODO =
focusManager.clearFocus()

Using Focus Manager

This closes the keyboard AND clears the focus from the TextField.

Solution 4 - Android

Hiding the keyboard on button click

To add with Gabriele Mariotti's solution, if you want to hide the keyboard conditionally, say after a button click, use this:

keyboardController?.hide()

For example, hide the keyboard after clicking the Add button:

var newWord by remember { mutableStateOf("") }
val keyboardController = LocalSoftwareKeyboardController.current

// Setup the text field with keyboard as provided by Gabriele Mariotti

...

Button(
		modifier = Modifier
				.height(56.dp),
		onClick = {
				if (!newWord.trim().isNullOrEmpty()) {
						wordViewModel.onAddWord(newWord.trim())
						newWord = ""
						keyboardController?.hide()
				}
		...

Solution 5 - Android

Edit after alpha-12 release: See @azizbekian response.

Pre-alpha-12 response

I found the solution here :)

fun hideKeyboard(activity: Activity) {
    val imm: InputMethodManager = activity.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
    var view = activity.currentFocus
    if (view == null) {
        view = View(activity)
    }
    imm.hideSoftInputFromWindow(view.windowToken, 0)
}

I just need to call the function above from my component:

// getting the context
val context = +ambient(ContextAmbient)

// textfield state
val text = +state { "" }

TextField(
    value = text.value,
    keyboardType = KeyboardType.Text,
    imeAction = ImeAction.Done,
    onImeActionPerformed = { 
        if (imeAction == ImeAction.Done) {
            hideKeyboard(context as Activity)
        }
    }
    onValueChange = { s -> text.value = s }
)

Solution 6 - Android

> implementation 'androidx.compose.material3:material3:1.0.0-alpha02'

Text Field With Hide Keyboard On Ime Action

@OptIn(ExperimentalComposeUiApi::class)
    @Composable
    fun TextFieldWithHideKeyboardOnImeAction() {
        val keyboardController = LocalSoftwareKeyboardController.current
        var text by rememberSaveable { mutableStateOf("") }
        TextField(
            value = text,
            onValueChange = { text = it },
            label = { Text("Label") },
            keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
            keyboardActions = KeyboardActions(
                onDone = {
                    keyboardController?.hide()
                    // do something here
                }
            )
        )
    }

Text Field With Hide Keyboard On Ime Action

Solution 7 - Android

I found a way to shut him down in the CoreTextField,use TextInputService to control the switch

val focus = LocalTextInputService.current
var text by remember{ mutableStateOf("")}
TextField(
    value = text,
    onValueChange = { text = it },
    keyboardOptions = KeyboardOptions.Default.copy(imeAction = ImeAction.Done, keyboardType = KeyboardType.Text),
    keyboardActions = KeyboardActions(onDone = { focus?.hideSoftwareKeyboard() }),
    singleLine = true
)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionnglauberView Question on Stackoverflow
Solution 1 - AndroidGabriele MariottiView Answer on Stackoverflow
Solution 2 - AndroidazizbekianView Answer on Stackoverflow
Solution 3 - Androidm.reiterView Answer on Stackoverflow
Solution 4 - AndroidHasanView Answer on Stackoverflow
Solution 5 - AndroidnglauberView Answer on Stackoverflow
Solution 6 - AndroidHari Shankar SView Answer on Stackoverflow
Solution 7 - AndroidYshhView Answer on Stackoverflow