Jetpack Compose关闭键盘时清除TextField焦点 避免两次返回退出应用
问题原因
这个是Android输入框架和Compose焦点系统的固有执行逻辑:
- 首次按下返回键时,事件优先被输入法服务消费,仅执行隐藏键盘操作,不会向下传递到App层的BackHandler,同时系统默认不会主动清除输入框焦点,所以
onFocusChanged回调不会触发 - 第二次按下返回键时,当前持有焦点的是BasicTextField,事件会先触发焦点清除逻辑,所以
onFocusChanged会回调,但事件仍然被焦点系统消费,不会传递到BackHandler - 第三次按下返回键时,当前没有消费事件的控件,事件才会传递到自定义的BackHandler中执行逻辑
解决方案
如果需要实现隐藏键盘同时自动清除BasicTextField焦点的效果,可以通过监听键盘可见状态,主动触发焦点清除,操作步骤如下:
- 首先在Activity的
onCreate方法中开启边到边显示,让Compose可以监听到键盘Insets变化:
WindowCompat.setDecorFitsSystemWindows(window, false)
- 在Compose代码中监听键盘可见状态,键盘隐藏时主动清除焦点,完整示例代码:
val focusManager = LocalFocusManager.current val valueState = remember { mutableStateOf(TextFieldValue(text = "")) } val isTextFieldFocused = remember { mutableStateOf(false) } // 监听键盘可见状态 val isKeyboardVisible by WindowInsets.ime.getIsVisibleAsState() LaunchedEffect(isKeyboardVisible) { // 仅在当前输入框持有焦点、键盘隐藏时清除焦点,避免影响其他输入框 if (!isKeyboardVisible && isTextFieldFocused.value) { focusManager.clearFocus() } } BackHandler { println("BackPressHandler") } BasicTextField( value = valueState.value, onValueChange = { valueState.value = it }, modifier = Modifier .fillMaxWidth() .onFocusChanged { focusState -> isTextFieldFocused.value = focusState.isFocused println("isFocused ${focusState.isFocused}") } )
修改后首次按下返回键隐藏键盘时,会主动触发焦点清除,onFocusChanged会正常回调,此时再按返回键就会直接触发BackHandler逻辑。
内容的提问来源于stack exchange,提问作者Phil Dukhov
相关产品推荐
相关产品推荐

