如何避免调用requestFocus()时触发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
相关产品推荐
相关产品推荐

