如何从 Jetpack ComposeTextField 关闭虚拟键盘?

我正在使用 Jetpack ComposeTextField,当用户按下操作按钮(imeActionPerformed参数)时,我想关闭虚拟键盘。

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 }
)
29862 次浏览

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 }
)

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.

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.

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()
}
...

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.

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

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
)