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

如何确保点击BasicTextField时始终隐藏手机键盘且保留光标

问题

我需要让计算器的BasicTextField显示光标但不弹出键盘。目前首次点击该组件时光标出现、键盘不弹出,但再次点击时键盘会弹出。此前我使用CompositionLocalProvider(LocalTextInputService provides null)实现,但该方法现已废弃。以下是我的当前代码:

BoxWithConstraints(
            modifier = modifier
                .fillMaxSize()
                .padding(16.dp)
        ) {
            val containerSize = minOf(maxWidth, maxHeight)
            val fontSize = containerSize * 0.25f
            val spacing = containerSize * 0.01f
            val allowedCharacters = "0123456789+-×÷−%.,"

            val keyboardController = LocalSoftwareKeyboardController.current
            val focusRequester = remember { FocusRequester() }
            val interactionSource = remember { MutableInteractionSource() }

            LaunchedEffect(interactionSource) {
                interactionSource.interactions.collect { interaction ->
                    if (interaction is PressInteraction.Release) {
                        focusRequester.requestFocus()
                    }
                }
            }
            DisposableEffect(Unit) {
                focusRequester.requestFocus()
                keyboardController?.hide()
                onDispose { }
            }

            Column(
                modifier = Modifier.fillMaxSize(),
                verticalArrangement = Arrangement.Bottom
            ) {
                BasicTextField(
                    value = viewModel.currentExpression.value,
                    onValueChange = { newValue ->
                        // Filter the input to allow only the specified characters
                        val filteredValue = newValue.filter { it in allowedCharacters }
                        viewModel.currentExpression.value = filteredValue
                    },
                    singleLine = true,
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(vertical = 8.dp, horizontal = 16.dp)
                        .focusRequester(focusRequester)
                        .onPreviewKeyEvent { keyEvent ->
                            if (keyEvent.type == KeyEventType.KeyDown &&
                                (keyEvent.key == Key.Enter || keyEvent.key == Key.NumPadEnter)) {
                                keyboardController?.hide()
                                true
                            } else {
                                false
                            }
                        },
                    maxLines = 1,
                    textStyle = TextStyle(
                        fontSize = fontSize.value.sp,
                        textAlign = TextAlign.End,
                        color = MaterialTheme.colorScheme.onSurface,
                        letterSpacing = spacing.value.sp
                    ),
                    keyboardOptions = KeyboardOptions.Default.copy(
                        imeAction = ImeAction.None,
                        keyboardType = KeyboardType.Number
                    ),
                    cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurface),
                    interactionSource = interactionSource
                )
            }
        }

请问如何确保BasicTextField始终隐藏键盘同时保持光标可见?

解决方案

废弃LocalTextInputService后,官方推荐直接给BasicTextField传递textInputService = null参数,这能从根源上阻止输入法服务绑定,彻底避免键盘弹出,同时保留光标显示和焦点状态。

修改后的核心代码

只需要在BasicTextField中添加一行关键参数:

BasicTextField(
    // 原有参数不变...
    cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurface),
    interactionSource = interactionSource,
    // 关键:禁用输入法服务,彻底阻止键盘弹出
    textInputService = null
)

精简后的完整代码

可以移除原代码中依赖keyboardController的冗余逻辑,让代码更简洁:

BoxWithConstraints(
    modifier = modifier
        .fillMaxSize()
        .padding(16.dp)
) {
    val containerSize = minOf(maxWidth, maxHeight)
    val fontSize = containerSize * 0.25f
    val spacing = containerSize * 0.01f
    val allowedCharacters = "0123456789+-×÷−%.,"

    val focusRequester = remember { FocusRequester() }
    val interactionSource = remember { MutableInteractionSource() }

    LaunchedEffect(interactionSource) {
        interactionSource.interactions.collect { interaction ->
            if (interaction is PressInteraction.Release) {
                focusRequester.requestFocus()
            }
        }
    }

    DisposableEffect(Unit) {
        focusRequester.requestFocus()
        onDispose { }
    }

    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Bottom
    ) {
        BasicTextField(
            value = viewModel.currentExpression.value,
            onValueChange = { newValue ->
                val filteredValue = newValue.filter { it in allowedCharacters }
                viewModel.currentExpression.value = filteredValue
            },
            singleLine = true,
            modifier = Modifier
                .fillMaxWidth()
                .padding(vertical = 8.dp, horizontal = 16.dp)
                .focusRequester(focusRequester),
            maxLines = 1,
            textStyle = TextStyle(
                fontSize = fontSize.value.sp,
                textAlign = TextAlign.End,
                color = MaterialTheme.colorScheme.onSurface,
                letterSpacing = spacing.value.sp
            ),
            keyboardOptions = KeyboardOptions.Default.copy(
                imeAction = ImeAction.None,
                keyboardType = KeyboardType.Number
            ),
            cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurface),
            interactionSource = interactionSource,
            textInputService = null
        )
    }
}

方案优势

  • 彻底禁用输入法服务,无论点击多少次都不会弹出键盘
  • 保留光标显示和焦点状态,完全符合计算器的交互需求
  • 移除冗余的键盘控制逻辑,代码更简洁易维护

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 13:14:57