ExposedDropdownMenuBox中OutlinedTextField焦点异常回跳问题求助
问题与解决方案
问题
使用androidx.compose.material:material 1.3.1版本时,将OutlinedTextField嵌套在ExposedDropdownMenuBox中出现异常行为:点击过该输入框后,手动关闭键盘,再点击其他输入框或滚动视图时,焦点总会强制跳回这个OutlinedTextField;仅当键盘保持开启状态时,输入框焦点切换才正常。
原因
这是Compose Material 1.x早期版本(1.3.x)中ExposedDropdownMenuBox的焦点管理bug:组件内部会在键盘关闭后错误地保留焦点绑定,导致焦点被强制拉回原输入框。
解决方法
方法1:手动管理焦点,主动释放
通过FocusRequester绑定输入框,在下拉菜单关闭、键盘关闭时主动释放焦点:
@OptIn(ExperimentalMaterialApi::class) @Composable fun ContributorComposable(contributor: Contributor, logbookEntryState: LogbookEntryState, enabled: Boolean) { // ... 原有代码 val focusRequester = remember { FocusRequester() } val keyboardController = LocalSoftwareKeyboardController.current ExposedDropdownMenuBox( expanded = expanded, onExpandedChange = { expanded = !expanded && enabled }, ) { Row(/* ... 原有参数 */) { OutlinedTextField( // ... 原有参数 modifier = Modifier .weight(1f) .focusRequester(focusRequester), // ... 原有参数 ) // ... 原有按钮/Spacer代码 } if (options.isNotEmpty()) ExposedDropdownMenu( expanded = expanded, modifier = Modifier.background(db_secondary_white), onDismissRequest = { expanded = false // 关闭菜单时释放焦点 focusRequester.freeFocus() keyboardController?.hide() }, ) { // ... 原有下拉项代码 } } // 监听键盘关闭事件,释放焦点 DisposableEffect(keyboardController) { val callback = object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { if (keyboardController?.isVisible == true) { keyboardController.hide() focusRequester.freeFocus() isEnabled = false } else { isEnabled = true } } } val dispatcher = ViewTreeOnBackPressedDispatcherOwner.getLocalOnBackPressedDispatcherOwner()?.onBackPressedDispatcher dispatcher?.addCallback(callback) onDispose { callback.remove() } } // ... 原有CustomTextField代码 }
方法2:升级Material依赖版本
该焦点bug在androidx.compose.material:material:1.4.0及以上版本已被官方修复,直接升级依赖即可解决问题:
dependencies { implementation 'androidx.compose.material:material:1.4.0' // 或更高稳定版本 }
方法3:调整组件结构,修复焦点捕获
如果暂时无法升级版本,可调整OutlinedTextField的嵌套结构,确保正确使用menuAnchor修饰符,避免ExposedDropdownMenuBox错误捕获焦点:
ExposedDropdownMenuBox( expanded = expanded, onExpandedChange = { expanded = !expanded && enabled }, ) { Row(verticalAlignment = CenterVertically, horizontalArrangement = Arrangement.End, modifier = Modifier.fillMaxWidth()) { OutlinedTextField( // ... 原有参数 modifier = Modifier .weight(1f) .menuAnchor(), // 必须添加此修饰符,关联ExposedDropdownMenuBox // ... 原有参数 ) // ... 原有按钮/Spacer代码 } // ... 原有下拉菜单代码 }
验证
应用上述任一方案后,手动关闭键盘,再点击其他输入框或滚动视图,焦点不会再跳回原OutlinedTextField,输入框焦点切换恢复正常。
内容的提问来源于stack exchange,提问作者c7n
相关产品推荐
相关产品推荐

