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

M3 OutlinedTextField文本无法选中、光标不可移动问题排查

问题:数字输入TextField无法选中文本、光标移动异常

问题背景

基于Material 3的OutlinedTextField封装了FormTextField组件,在实现仅接受数字的输入字段时,遇到文本完全无法选中、光标无法正常移动的问题。

封装的FormTextField代码

@Composable
fun FormTextField(
    value: TextFieldValue,
    onValueChange: (TextFieldValue) -> Unit,
    modifier: Modifier = Modifier,
    labelTxt: String,
    placeholderTxt: String,
    focusedBorderColor: Color,
    textColor: Color = colorResource(id = R.color.black),
    keyboardOptions: KeyboardOptions,
    keyboardActions: KeyboardActions,
    trailingIcon: @Composable() (() -> Unit)? = null,
) {
    OutlinedTextField(
        value = value,
        onValueChange = onValueChange,
        label = {
            Text(labelTxt, color = focusedBorderColor, fontSize = 12.sp)
        },
        placeholder = {
            Text(placeholderTxt, fontSize = 12.sp)
        },
        textStyle = TextStyle(
            color = textColor
        ),
        shape = RoundedCornerShape(8.dp),
        colors = OutlinedTextFieldDefaults.colors(
            focusedBorderColor = focusedBorderColor,
            cursorColor = focusedBorderColor,
            unfocusedBorderColor = Color(0xFFBEBEBE),
        ),
        modifier = modifier,
        keyboardOptions = keyboardOptions,
        keyboardActions = keyboardActions,
        trailingIcon = trailingIcon
    )
}

出问题的使用代码片段

在EditProductStockBottomSheet中使用FormTextField时,onValueChange的处理逻辑如下:

FormTextField(
    modifier = Modifier.weight(0.7f, true),
    value = updatedStock,
    onValueChange = { newVal ->
        val newText = newVal.text.filter { it.isDigit() || it == '-' || it == '.' }
        // 问题所在:直接创建新的TextFieldValue,丢失了selection和composition状态
        updatedStock = TextFieldValue(newText)
    },
    // 其他参数...
)

问题诊断

这不是2021年那篇焦点期间文本选择的问题导致的,核心原因是:
TextFieldValue包含三个核心状态:text(文本内容)、selection(光标/选择范围)、composition(输入法合成状态)。直接通过TextFieldValue(newText)创建新对象时,会丢失原有的selection和composition信息,导致TextField无法正确跟踪光标位置和文本选择状态,从而出现无法选中文本、光标移动异常的现象。

解决方案

修改onValueChange的处理逻辑,使用copy方法保留原TextFieldValue的selection和composition状态,并根据过滤后的文本长度调整光标位置,避免光标超出文本范围:

修复后的onValueChange代码

FormTextField(
    modifier = Modifier.weight(0.7f, true),
    value = updatedStock,
    onValueChange = { newVal ->
        val filteredText = newVal.text.filter { it.isDigit() || it == '-' || it == '.' }
        // 调整光标位置:如果原光标在过滤后的文本长度范围内,保留原位置;否则移到文本末尾
        val adjustedSelection = when {
            newVal.selection.start <= filteredText.length -> newVal.selection
            else -> TextRange(filteredText.length)
        }
        // 使用copy方法保留原有状态,仅更新文本和调整后的光标位置
        updatedStock = newVal.copy(
            text = filteredText,
            selection = adjustedSelection
        )
    },
    // 其他参数...
)

同步修复LaunchedEffect中的更新逻辑

在扫描条码后更新updatedStock时,同样使用copy方法保留状态:

LaunchedEffect(key1 = scannedBarcode) {
    if (scannedBarcode.isNullOrEmpty() || !productDetails.getPossibleBarcodes().contains(scannedBarcode)) 
        return@LaunchedEffect
    val updatedStockAsInt = updatedStock.text.toIntOrNull()
    if (updatedStockAsInt != null) {
        updatedStock = updatedStock.copy(
            text = (updatedStockAsInt + 1).toString()
        )
    }
    navViewModel.setScannedBarcode("")
}

原理说明

通过copy方法复用原TextFieldValue的selection和composition状态,同时根据过滤后的文本长度调整光标位置,确保TextField始终能正确跟踪输入状态,从而恢复正常的文本选择和光标移动功能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 03:50:12