【问题标题】:How to toggle IME keyboard open/close in Compose?如何在 Compose 中切换 IME 键盘打开/关闭?
【发布时间】:2021-11-04 18:29:27
【问题描述】:

在我的应用程序中,我有一个 TextField 和一个应该显示/隐藏 IME 键盘的按钮。我已经阅读了有关控制软键盘以及如何显示或隐藏它的所有内容,但没有阅读如何切换。 This SO 帖子是相关的,但不完全符合我的要求。

我遇到的问题是我需要跟踪键盘何时打开和关闭。当然可以通过点击TextField来打开键盘,也可以通过按返回按钮来关闭它。我找不到这些操作的任何挂钩或回调,所以我可以分配 isKeyboardOpen 布尔值。

因此,我可以从Toggle keyboard! 按钮切换键盘,但只要我“手动”打开它(点击文本字段)或关闭它(按返回按​​钮),切换按钮状态无法更新,我需要按两次才能显示/隐藏键盘。

到目前为止,我已经尝试了以下方法:

  1. BackHandler - 无效
  2. Modifier.pointerInput(Unit) 和 detectTapGestures - 这些回调永远不会在点击 TextField 时被击中
  3. onKeyEvent 和 onPreviewKeyEvent - 它们似乎仅用于硬件键盘按键。我试图拦截后面的新闻,就像我们在 Android 视图世界中所做的那样:action == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK,但没有运气

这是这两个元素的代码,如下图所示:

                Surface {

                var isKeyboardOpen by remember { mutableStateOf(false) }
                val keyboardController = LocalSoftwareKeyboardController.current

                Column {
                    Button(onClick = {
                        isKeyboardOpen = !isKeyboardOpen
                        if (isKeyboardOpen) keyboardController?.show() else keyboardController?.hide()
                    }
                    ) {
                        Text("Toggle keyboard!")
                    }

                    //...

                    BackHandler(isKeyboardOpen) {
                        Log.d("TextField", "backPressed - never called")
                    }

                    var text by remember { mutableStateOf("") }

                    TextField(
                        value = text,
                        onValueChange = { text = it },
                        modifier = Modifier.pointerInput(Unit) {
                            detectTapGestures(
                                onTap = { Log.d("TextField", "onTap - never called") },
                                onPress = { Log.d("TextField", "onPress - never called") },
                            )
                        }.onKeyEvent { event ->
                            // callback never hit
                            if (event.type == KeyEventType.KeyUp && event.key == Key.Back) {
                                //....
                            }
                            true
                        }
                    )
                }
            }

Gif of trying to toggle keyboard open/closed from a button

如何在撰写中实现键盘切换按钮?有可能吗?

【问题讨论】:

  • 也许是以下解决方案之一:stackoverflow.com/questions/25216749/…
  • @Johann 谢谢!虽然这些看起来像基于 Android 视图的解决方案。我最终设法让它与this proposed solution 一起工作,但它混合了撰写和视图 - 基本上检查当前窗口的高度,我认为这些基于视图的方法也是如何解决它的键盘。

标签: android kotlin android-jetpack-compose


【解决方案1】:

您可以使用 WindowInsets 来检测键盘是打开还是关闭。

按照these 的说明添加和设置伴奏插图库。

设置完成后,您可以像这样创建按钮。

val insets = LocalWindowInsets.current
val keyboardController = LocalSoftwareKeyboardController.current

Button(onClick = {
    if (insets.ime.isVisible) keyboardController?.hide() else keyboardController?.show()
}) {
    Text("Toggle keyboard!")
}

【讨论】:

  • 谢谢!使用 Compose 解决方案会很好,但是使用上面的代码,我的切换按钮只会隐藏键盘并且不会显示它:( 我不知道为什么?
  • 我在我的应用程序中尝试了这段代码,它运行良好。您是否添加了WindowCompat.setDecorFitsSystemWindows(window, false) 并使用ProvideWindowInsets 包装了您的顶级可组合?
  • 我还没有完成WindowCompat.setDecorFitsSystemWindows(window, false),现在看来已经解决了!它似乎确实稍微改变了布局(顶部填充似乎被忽略了,视图直接射到屏幕顶部)所以可能需要一个解决方法并了解setDecorFitsSystemWindows 的确切作用。感谢您的解决方案!
  • 它只是为您的应用程序提供了整个屏幕区域供您使用。他们称之为edge-to-edge。如果你不想要这个,你可以将你的顶层可组合包装在一个盒子里并添加一个Modifier.systemBarsPadding()。这会将您的应用内容推送到系统栏之外。
【解决方案2】:

您可以为此使用 KeyboardVisibilityEvent 库

KeyboardVisibilityEvent.setEventListener(
    getActivity(),
    new KeyboardVisibilityEventListener() {
        @Override
        public void onVisibilityChanged(boolean isOpen) {
           // do your thing here !!
        }
    });

【讨论】:

  • 谢谢!不确定这是否可以轻松地与 Compose 合并?这是一个选项,但我正在寻找一种仅撰写的方法。
猜你喜欢
  • 1970-01-01
  • 2012-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-26
  • 2019-01-07
  • 1970-01-01
  • 2013-02-03
相关资源
最近更新 更多