如何从 Jetpack Compose TextField 关闭虚拟键盘?

Posted

技术标签:

【中文标题】如何从 Jetpack Compose TextField 关闭虚拟键盘?【英文标题】:How to close the virtual keyboard from a Jetpack Compose TextField? 【发布时间】:2020-03-26 17:20:18 【问题描述】:

我正在使用 Jetpack Compose TextField,我想在用户按下操作按钮(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 
)

【问题讨论】:

【参考方案1】:

在 alpha-12 发布后编辑: 请参阅 @azizbekian 的回复。

pre-alpha-12 响应

我找到了解决方案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)

我只需要从我的组件中调用上面的函数:

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

【讨论】:

【参考方案2】:

通过1.0.x可以使用LocalSoftwareKeyboardController类来控制当前的软键盘,然后使用hide方法:

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

此解决方案会关闭键盘而不从当前TextField 移除焦点。

只是为了突出区别:

val focusManager = LocalFocusManager.current
focusManager.clearFocus()

此代码关闭键盘,从 TextField 移除焦点。

【讨论】:

这是每个 android 开发者的梦想 这与 focusManager 方法 (***.com/a/66259111/2911458) 有什么区别?我们应该什么时候使用它们? @stkent 这个解决方案只隐藏键盘。另一种解决方案也从当前的 TextField 中移除焦点(光标仍在显示,它可能仍被突出显示等) 在两种解决方案之间进行选择时,请同时注意 ux-continuity:默认行为:向后滑动一次隐藏键盘,第二次滑动清除焦点。 @stkent 了解更多详情,请参阅下面***.com/a/68650009/12871582的回答【参考方案3】:

从 compose 1.0.0-alpha12 开始(在 compose 1.0.5 中仍然有效)onImeActionPerformed 已被弃用,建议的方法是使用 keyboardActionskeyboardOptions 的组合:

    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() 将负责关闭软键盘。

【讨论】:

【参考方案4】:

在点击按钮时隐藏键盘

要添加Gabriele Mariotti's solution,如果你想有条件地隐藏键盘,比如点击按钮后,使用这个:

keyboardController?.hide()

例如,点击添加按钮后隐藏键盘:

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

【讨论】:

【参考方案5】:

1.0.0 中,您可以使用SoftwareKeyboardControllerFocusManager 来执行此操作。

此答案侧重于它们的差异。


设置:

var text by remember  mutableStateOf("")

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


软件键盘控制器:

基于@Gabriele Mariottis 的回答。

val keyboardController = LocalSoftwareKeyboardController.current

// TODO =
keyboardController?.hide()

这只会关闭键盘,但不会从任何聚焦的 TextField 中清除焦点(注意光标和粗下划线)。


焦点管理器:

基于@azizbekians 的回答。

val focusManager = LocalFocusManager.current

// TODO =
focusManager.clearFocus()

这会关闭键盘并从 TextField 中清除焦点。

【讨论】:

【参考方案6】:

实现'androidx.compose.material3:material3:1.0.0-alpha02'

Ime 操作中带有隐藏键盘的文本字段

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

【讨论】:

以上是关于如何从 Jetpack Compose TextField 关闭虚拟键盘?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Jetpack compose 中的 drawable 加载图像?

如何从 Jetpack Compose 中的 URL 加载图像? [复制]

Jetpack Compose 从入门到入门

Jetpack Compose 从入门到入门

Jetpack Compose 从入门到入门

Jetpack Compose 从入门到入门