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

Compose信用卡格式输入框填充满后删除异常问题求助

问题原因及修复方案

核心问题:输入内容长度判断逻辑错误

你在onValueChange里的判断条件是原文本长度<=16时才更新内容,这会导致当原文本已经是16位时,用户输入新字符会让it的长度变成17,此时原文本长度16满足<=16的条件,text会被赋值为17位的字符串。而你的VisualTransformation和OffsetMapping都是基于16位原文本设计的,超长的原文本会导致光标偏移映射混乱,最终引发删除操作异常。

修复步骤

1. 修正onValueChange的长度限制逻辑

把判断条件从原文本长度改为新输入内容的长度不超过16,确保存储的text始终最多16位:

onValueChange = { newText ->
    if (newText.length <= 16) {
        text = newText
    }
}

2. 优化VisualTransformation的冗余处理(可选)

因为已经通过onValueChange限制了text长度不超过16,所以filter方法里的截断逻辑可以简化,避免重复处理:

visualTransformation = object : VisualTransformation {
    override fun filter(text: AnnotatedString): TransformedText {
        var out = ""
        for (i in text.text.indices) {
            out += text.text[i]
            if (i % 4 == 3 && i != 15) out += "-"
        }
        return TransformedText(
            AnnotatedString(out),
            creditCardOffsetMapping
        )
    }
}

3. 验证OffsetMapping逻辑

你的creditCardOffsetMapping逻辑是正确的,16位原文本转换后是19位(包含3个分隔符),偏移映射的计算没问题,修复长度限制后即可正常工作。

修复后的完整代码示例

// XXXX-XXXX-XXXX-XXXX
var text by remember { mutableStateOf("") }
OutlinedTextField(
    value = text,
    onValueChange = { newText ->
        if (newText.length <= 16) {
            text = newText
        }
    },
    visualTransformation = object : VisualTransformation {
        override fun filter(text: AnnotatedString): TransformedText {
            var out = ""
            for (i in text.text.indices) {
                out += text.text[i]
                if (i % 4 == 3 && i != 15) out += "-"
            }
            return TransformedText(
                AnnotatedString(out),
                creditCardOffsetMapping
            )
        }
    }
)

// Making XXXX-XXXX-XXXX-XXXX string.
val creditCardOffsetMapping = object : OffsetMapping {
    override fun originalToTransformed(offset: Int): Int {
        if (offset <= 3) return offset
        if (offset <= 7) return offset + 1
        if (offset <= 11) return offset + 2
        if (offset <= 16) return offset + 3
        return 19
    }

    override fun transformedToOriginal(offset: Int): Int {
        if (offset <= 4) return offset
        if (offset <= 9) return offset - 1
        if (offset <= 14) return offset - 2
        if (offset <= 19) return offset - 3
        return 16
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 08:18:15