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

Jetpack Compose 1.5.0下拉菜单点击唤起键盘问题求助

问题

将Jetpack Compose版本升级至1.5.0后,自定义下拉菜单组件出现异常:点击下拉菜单展开时,软件键盘会一同弹出。升级前该功能正常,仅展开菜单不会唤起键盘。

自定义下拉菜单代码如下:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun <T> DropDownMenu(
    items: Collection<T>,
    expanded: Boolean,
    enabled: Boolean,
    modifier: Modifier = Modifier,
    selectedItem: T = items.first(),
    label: String? = null,
    formatter: (T) -> String = { it.toString() },
    minNumberOfItems: Int = 2,
    maxNumberOfItems: Int = 4,
    onExpandedChange: (Boolean) -> Unit,
    onDismissRequest: () -> Unit,
    onClick: (T) -> Unit = {},
) {
    var currentItem = selectedItem
    val localDensity = LocalDensity.current
    var itemHeight by remember { mutableStateOf(0.dp) }
    var heightCalculated = false

    ExposedDropdownMenuBox(
        modifier = modifier,
        expanded = expanded && enabled,
        onExpandedChange = onExpandedChange,
    ) {

        TextField(
            value = formatter(currentItem),
            enabled = enabled,
            onValueChange = {},
            readOnly = true,
            singleLine = true,
            textStyle = Typography.bodySmall,
            trailingIcon = {
                if (enabled) {
                    ExposedDropdownMenuDefaults.TrailingIcon(
                        expanded = expanded
                    )
                }
            },
            modifier = Modifier.menuAnchor(),
            supportingText = { label?.let { Text(it) } },
        )

        DropdownMenu(
            expanded = expanded && enabled, onDismissRequest = onDismissRequest,
            modifier = Modifier.height(
                itemHeight * (items.size.coerceIn(
                    minNumberOfItems,
                    maxNumberOfItems
                ) + 0.3f)
            ),
            properties = PopupProperties(focusable = false)
        ) {
            items.forEach { item ->
                DropdownMenuItem(
                    text = { Text(text = formatter(item)) },
                    onClick = {
                        currentItem = item
                        onClick(item)
                    },
                    modifier = Modifier.onGloballyPositioned { coordinates ->
                        if (!heightCalculated) {
                            itemHeight = with(localDensity) { coordinates.size.height.toDp() }
                            heightCalculated = true
                        }
                    }
                )
            }
        }
    }
}

调用该组件的父布局中包含点击空白区域隐藏键盘的逻辑,代码如下:

keyboardController = LocalSoftwareKeyboardController.current

Column(
    Modifier
        .fillMaxSize()
        .pointerInput(Unit) {
            detectTapGestures(onTap = {
                localFocusManager?.clearFocus()
            })
        }) 
{
    ...
}

原因分析

Jetpack Compose 1.5.0对TextField的焦点处理逻辑做了调整:即便设置了readOnly = true,点击TextField时仍会请求焦点,而焦点变化会触发软件键盘弹出。升级前的版本中,readOnly状态的TextField点击不会请求焦点,因此不会唤起键盘。

解决方案

通过控制TextField的焦点和键盘配置,阻止键盘弹出:

修改后的TextField代码片段:

val focusManager = LocalFocusManager.current

TextField(
    value = formatter(currentItem),
    enabled = enabled,
    onValueChange = {},
    readOnly = true,
    singleLine = true,
    textStyle = Typography.bodySmall,
    trailingIcon = {
        if (enabled) {
            ExposedDropdownMenuDefaults.TrailingIcon(
                expanded = expanded
            )
        }
    },
    modifier = Modifier
        .menuAnchor()
        .pointerInput(Unit) {
            detectTapGestures(onTap = {
                // 直接触发菜单展开,阻止TextField获取焦点
                onExpandedChange(!expanded)
                focusManager.clearFocus()
            })
        },
    supportingText = { label?.let { Text(it) } },
    keyboardOptions = KeyboardOptions.Default.copy(imeAction = ImeAction.None),
    keyboardActions = KeyboardActions(onAny = { focusManager.clearFocus() })
)

额外优化(可选)

如果上述方法仍有问题,可在ExposedDropdownMenuBox的回调中主动清除焦点:

ExposedDropdownMenuBox(
    modifier = modifier,
    expanded = expanded && enabled,
    onExpandedChange = {
        onExpandedChange(it)
        if (it) {
            focusManager.clearFocus()
        }
    },
)

通过以上修改,即可恢复升级前的行为:点击下拉菜单仅展开菜单,不会唤起软件键盘。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 20:47:05