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

如何避免调用requestFocus()时触发Button的onClick()方法

Compose中请求Button焦点时避免触发onClick的解决方案

问题场景

页面加载完成后TextField默认获焦,在TextField中按下ENTER键时,通过FocusRequester让Button获得焦点,但此时Button的onClick方法会被意外触发,打印出"Clicked on Button",需要实现仅让Button获焦而不触发点击事件。

问题原因

原代码仅消费了Enter键的KeyDown事件,而KeyUp事件会继续传递。当Button获得焦点后,接收到Enter的KeyUp事件时,Compose默认会将其视为触发按钮点击的操作(等同于用户按下Enter键点击已获焦的按钮),因此触发了onClick。

解决代码

val focusRequester = remember { listOf(FocusRequester(), FocusRequester()) }
val focusedState = remember { mutableStateListOf(true, false) }

Column {
    OutlinedTextField(
        value = TextFieldValue("test"),
        onValueChange = { },
        modifier = Modifier
            .onKeyEvent {
                // 拦截Enter键的所有事件(KeyDown和KeyUp)
                if (it.key.keyCode == Key.Enter.keyCode) {
                    if (it.type == KeyEventType.KeyDown) {
                        focusRequester[1].requestFocus()
                    }
                    return@onKeyEvent true
                }
                false
            }
            .focusRequester(focusRequester[0])
            .onFocusChanged {
                focusedState[0] = it.isFocused
            }
            .focusable(),
        colors = textFieldColors(focusedState[0]))

    OutlinedButton(modifier = Modifier
        .focusRequester(focusRequester[1])
        .onFocusChanged {
            focusedState[1] = it.isFocused
        }
        .focusable(),
        colors = getColorByFocusedState(focusedState[1]),
        onClick = { println("Clicked on Button.") }) {
        Text(text = "Button")
    }
}

LaunchedEffect(Unit) {
    focusRequester[0].requestFocus()
}

解决方案说明

在TextField的onKeyEvent中,不再仅处理KeyDown事件,而是直接判断是否为Enter键的事件,不管是KeyDown还是KeyUp都返回true,完整消费整个Enter按键的事件流。这样后续的KeyUp事件就不会传递到Button,也就不会触发默认的点击行为了。

内容的提问来源于stack exchange,提问作者Captain Jacky

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 17:40:23