【问题标题】:How to close the virtual keyboard from a Jetpack Compose TextField?如何从 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 }
)

【问题讨论】:

    标签: android kotlin android-jetpack-compose android-input-method android-compose-textfield


    【解决方案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 方法 (stackoverflow.com/a/66259111/2911458) 有什么区别?我们应该什么时候使用它们?
      • @stkent 这个解决方案只隐藏键盘。另一种解决方案也从当前的 TextField 中移除焦点(光标仍在显示,它可能仍被突出显示等)
      • 在两种解决方案之间进行选择时,请同时注意 ux-continuity:默认行为:向后滑动一次隐藏键盘,第二次滑动清除焦点。
      • @stkent 了解更多详情,请参阅下面stackoverflow.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
                            }
                        )
                    )
                }
            

            【讨论】:

              猜你喜欢
              • 2021-08-26
              • 1970-01-01
              • 2022-11-21
              • 2016-11-05
              • 2021-11-16
              • 1970-01-01
              • 2021-05-06
              • 1970-01-01
              • 2020-05-17
              相关资源
              最近更新 更多