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

Android Jetpack Compose如何同步OutlinedTextField焦点与trailingIcon点击

解决方案

修改后的完整实现代码如下:

@Composable
fun DownMenuTextField(
    @StringRes titleId: Int,
    selectedText: String,
    suggestions: List<String>,
    onValueChange: (String) -> Unit
) {
    var expanded by remember { mutableStateOf(false) }
    var textFieldSize by remember { mutableStateOf(Size.Zero) }
    // 新增焦点请求器,用于主动控制输入框焦点
    val focusRequester = remember { FocusRequester() }
    val icon = if (expanded) Icons.Filled.ArrowDropUp else Icons.Filled.ArrowDropDown

    Column {
        OutlinedTextField(
            value = selectedText,
            readOnly = true,
            onValueChange = { onValueChange(it) },
            modifier = Modifier
                .fillMaxWidth()
                .onGloballyPositioned { coordinates ->
                    textFieldSize = coordinates.size.toSize()
                }
                // 绑定焦点请求器
                .focusRequester(focusRequester)
                // 输入框点击事件,同时触发菜单切换和焦点请求
                .clickable {
                    expanded = !expanded
                    focusRequester.requestFocus()
                }
                // 可选:失去焦点时自动收起菜单,保证状态一致性
                .onFocusChanged { focusState ->
                    if (!focusState.isFocused) {
                        expanded = false
                    }
                },
            label = {
                CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
                    Text(
                        text = stringResource(titleId),
                        style = MaterialTheme.typography.body2
                    )
                }
            },
            trailingIcon = {
                Icon(icon, "contentDescription",
                    Modifier
                        .focusable(false)
                        .clickable {
                            expanded = !expanded
                            // 点击图标时同时请求输入框焦点
                            focusRequester.requestFocus()
                        })
            }
        )

        DropdownMenu(
            expanded = expanded,
            onDismissRequest = { 
                expanded = false 
                // 关闭菜单时同步清除焦点
                focusRequester.freeFocus()
            },
            modifier = Modifier
                .width(with(LocalDensity.current) { textFieldSize.width.toDp() })
        ) {
            suggestions.forEach { label ->
                DropdownMenuItem(onClick = {
                    onValueChange(label)
                    expanded = false
                    focusRequester.freeFocus()
                }) {
                    Text(text = label)
                }
            }
        }
    }
}

注意使用前需要导入Compose焦点相关的依赖包,核心导入项包括androidx.compose.ui.focus.FocusRequester、androidx.compose.ui.focus.focusRequester、androidx.compose.ui.focus.onFocusChanged

核心改动说明

  • 新增FocusRequester实例:跳过输入框默认的焦点触发逻辑,可主动控制输入框的焦点状态
  • 给OutlinedTextField新增点击事件:原本只读状态的输入框不会响应自定义点击逻辑,添加clickable修饰符后,点击输入框任意区域都会同时触发菜单展开/收起、输入框获焦两个动作
  • 调整尾部图标的点击逻辑:在原有切换菜单状态的基础上,增加请求输入框焦点的逻辑,保证点击图标时两个效果同时触发
  • 补充状态同步逻辑:新增焦点变化监听、菜单关闭时清除焦点的逻辑,避免出现输入框持有焦点但菜单收起、菜单展开但输入框无焦点的异常状态

内容的提问来源于stack exchange,提问作者Evgenii Doikov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 07:51:01