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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 21:46:07