You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Kotlin Desktop Compose中触发PC键盘输入事件

Jetpack Compose 键盘输入事件触发与监听实现方案

1. 软键盘主动弹出/收起触发

适用于需要在特定场景自动唤起输入键盘的POS场景,比如进入收款页自动弹出金额输入键盘:

@Composable
fun PaymentInputPage() {
    // 绑定输入框焦点请求器
    val inputFocusRequester = remember { FocusRequester() }
    // 获取软键盘控制器
    val keyboardController = LocalSoftwareKeyboardController.current

    // 页面渲染完成后自动请求焦点并弹出键盘
    LaunchedEffect(Unit) {
        inputFocusRequester.requestFocus()
        keyboardController?.show()
    }

    TextField(
        value = "",
        onValueChange = { /* 处理输入逻辑 */ },
        placeholder = { Text("请输入收款金额") },
        modifier = Modifier.focusRequester(inputFocusRequester),
        keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
    )

    // 手动触发收起键盘
    Button(onClick = { keyboardController?.hide() }) {
        Text("完成输入")
    }
}

相关注意事项:

  • 如果需要模拟输入指定内容,直接修改TextField绑定的状态变量即可,不需要手动发送键盘事件,稳定性更高
  • 部分定制ROM的POS设备软键盘弹出逻辑有差异,可在Activity的onCreate中配置window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)兜底

2. 物理键盘/外接设备输入事件监听

POS设备大多外接扫码枪、实体数字键盘,这类输入属于物理按键事件,无需弹出软键盘即可监听:

@Composable
fun ScanGoodsPage() {
    // 存储扫码/按键输入的内容
    var scanInput by remember { mutableStateOf("") }
    val rootFocusRequester = remember { FocusRequester() }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .focusRequester(rootFocusRequester)
            // 允许组件获取焦点
            .focusable()
            // 监听物理按键事件
            .onKeyEvent { event ->
                if (event.type == KeyEventType.KeyDown) {
                    when (event.key) {
                        // 监听数字按键输入
                        Key.NumPad0, Key.NumPad1, Key.NumPad2, Key.NumPad3, Key.NumPad4,
                        Key.NumPad5, Key.NumPad6, Key.NumPad7, Key.NumPad8, Key.NumPad9,
                        Key.D0, Key.D1, Key.D2, Key.D3, Key.D4,
                        Key.D5, Key.D6, Key.D7, Key.D8, Key.D9 -> {
                            scanInput += event.key.toString().last()
                            true
                        }
                        // 监听回车,扫码枪默认扫码结束后会发送回车事件
                        Key.Enter -> {
                            // 处理扫码结果逻辑:查询商品信息、添加到购物车等
                            handleScanResult(scanInput)
                            scanInput = ""
                            true
                        }
                        // 其他事件不消费,继续向下传递
                        else -> false
                    }
                } else false
            }
    ) {
        Text("当前扫码内容:$scanInput")
    }

    // 页面加载后自动请求根布局焦点,保证能监听到所有按键事件
    LaunchedEffect(Unit) {
        rootFocusRequester.requestFocus()
    }
}

相关注意事项:

  • 必须给监听事件的组件添加focusable()修饰,且组件处于焦点状态才能收到按键事件
  • 要全局监听页面所有按键的话,直接把onKeyEvent修饰符绑定到页面根布局即可
  • 对于连续快速输入的扫码场景,Compose状态更新性能足够支撑,不需要额外做防抖处理

3. 输入内容拦截校验

POS场景经常需要限制输入格式,比如金额只能保留两位小数,直接在输入回调中处理即可:

var payAmount by remember { mutableStateOf("") }
TextField(
    value = payAmount,
    onValueChange = { input ->
        // 限制只能输入数字和小数点,最多保留两位小数
        val validRegex = Regex("^\\d*\\.?\\d{0,2}$")
        if (input.matches(validRegex)) {
            payAmount = input
        }
    },
    label = { Text("收款金额") },
    keyboardOptions = KeyboardOptions(
        keyboardType = KeyboardType.Number,
        imeAction = ImeAction.Done
    )
)

内容的提问来源于stack exchange,提问作者Prasa Dev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 07:36:04