【问题标题】:How to trigger PC Keyboard inputs in Kotlin Desktop Compose如何在 Kotlin Desktop Compose 中触发 PC 键盘输入
【发布时间】:2021-11-01 12:33:24
【问题描述】:

我打算使用 Kotlin Jetpack Compose 开发一个 POS 系统,我想知道如何在我的项目中触发键盘输入事件。

【问题讨论】:

    标签: kotlin android-jetpack-compose compose-desktop


    【解决方案1】:

    在 Compose Desktop 中可以使用 onKeyEvent Window 参数监听关键事件:

    Window(
        onCloseRequest = ::exitApplication,
        visible = visible,
        onKeyEvent = {
            if (it.isCtrlPressed && it.key == Key.A) {
                println("Ctrl + A is pressed")
                true
            } else {
                // let other handlers receive this event
                false
            }
        }
    ) {
        App()
    }
    

    另一个同样适用于 Android 中 Compose 的选项是使用 Modifier.onKeyEvent。正如文档所说:

    将允许它在它(或其子之一)获得焦点时拦截硬件键事件。

    因此,您需要使一个项目或它的一个子项目具有焦点和焦点。在this article中查看更多关于撰写中的焦点

    为此,您需要一个FocusRequester,在我的示例中,我在使用LaunchedEffect 渲染视图时询问焦点。

    对于未来的注意事项,如果用户点击文本字段或其他可聚焦元素将获得焦点,您的视图将失去它。如果这个焦点视图在你的视图中,onKeyEvent 处理程序,它仍然可以工作。

    空框不能成为焦点,因此您需要使用修饰符添加一些大小。它仍然是不可见的:

    val requester = remember { FocusRequester() }
    Box(
        Modifier
            .onKeyEvent {
                if (it.isCtrlPressed && it.key == Key.A) {
                    println("Ctrl + A is pressed")
                    true
                } else {
                    // let other handlers receive this event
                    false
                }
            }
            .focusRequester(requester)
            .focusable()
            .size(10.dp)
    )
    LaunchedEffect(Unit) {
        requester.requestFocus()
    }
    

    或者,只需将内容添加到 Box,这样它就会拉伸并且不再需要 .size 修饰符

    【讨论】:

    • 如果我想触发 2 个 keyEvents 怎么办。如果我为另一个按钮复制并粘贴相同的内容,则只有第二个有效。有什么帮助吗?
    • @XaviSeguraArdévol 在您的应用程序中只能关注一项。在this article 中查看有关撰写焦点的更多信息(最初答案中的链接已损坏,已更新)。你想听整个应用程序的关键事件,还是特定视图?作为使用requester.requestFocus() 的示例,您可以使按钮集中在点击上。
    • @PhilipDukhov 你建议什么教程开始学习 kotlin android 中的 jetpack compose
    • @sashabeliy 以documentation开头,挺好的,教程也很简单
    • 需要注意的是,在API的这个阶段,用鼠标点击窗口中的焦点框后,焦点似乎丢失了。是否真的需要手动处理这个问题,例如单击再次应用焦点?
    【解决方案2】:

    当您设置焦点并出于某种原因单击应用程序窗口内部时,遵循 Philip 答案的第二个选项可能会出现奇怪的行为。这样做可能会“失去”焦点,并且关键事件没有得到妥善处理。

    为了避免这种情况,建议通过添加点击/点击修饰符手动处理此问题,该修饰符仅指定当检测到点击/点击时requester 再次请求焦点。见下文:

    val requester = FocusRequester()
      Box(
        Modifier
           //pointer input handles [onPress] to force focus to the [requester]
          .pointerInput(key1 = true) {
            detectTapGestures(onPress = {
              requester.requestFocus()
            })
          }
          .onKeyEvent {
            if (it.isCtrlPressed && it.key == Key.A) {
              println("Ctrl + A is pressed")
              true
            } else {
              // let other handlers receive this event
              false
            }
          }
          .focusRequester(requester)
          .focusable()
          .fillMaxSize()
          .background(Color.Cyan)
      )
      LaunchedEffect(Unit) {
        requester.requestFocus()
      }
    

    【讨论】:

      猜你喜欢
      • 2011-08-17
      • 2017-11-21
      • 1970-01-01
      • 2012-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-24
      相关资源
      最近更新 更多