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
相关产品推荐
相关产品推荐

