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

使用VisualTransformation时TextField触发应用崩溃问题求助

解决Jetpack Compose手机号VisualTransformation点击崩溃问题

问题原因

崩溃的核心是原始文本为空时,transformedToOriginal返回了超出原始文本有效范围的值。你的代码硬编码返回10,但此时原始文本长度为0,有效偏移区间是[0,0],10不在这个范围内,直接触发IllegalStateException。

修复方案

修改OffsetMapping的实现,结合当前输入文本的实际长度动态计算偏移,确保返回值始终在有效范围内:

private fun phoneNumberInputFormatter(text: AnnotatedString): TransformedText {
    val mask = "xxx-xxx-xxxx"
    val trimmed = if (text.text.length >= 10) text.text.substring(0..9) else text.text

    val annotatedString = AnnotatedString.Builder().run {
        for (i in trimmed.indices) {
            append(trimmed[i])
            if (i == 2 || i == 5) {
                append("-")
            }
        }
        pushStyle(SpanStyle(color = Color.LightGray))
        append(mask.takeLast(mask.length - length))
        toAnnotatedString()
    }

    val phoneNumberOffsetTranslator = object : OffsetMapping {
        override fun originalToTransformed(offset: Int): Int {
            // 限制原始偏移不超过输入文本长度
            val actualOffset = offset.coerceAtMost(trimmed.length)
            return when {
                actualOffset <= 2 -> actualOffset
                actualOffset <= 5 -> actualOffset + 1
                actualOffset <= 9 -> actualOffset + 2
                else -> annotatedString.length // 返回转换后文本的实际长度,而非固定12
            }
        }

        override fun transformedToOriginal(offset: Int): Int {
            // 限制转换后的偏移不超过转换后文本长度
            val actualOffset = offset.coerceAtMost(annotatedString.length)
            val originalOffset = when {
                actualOffset <= 2 -> actualOffset
                actualOffset <= 6 -> actualOffset - 1 // 适配第一个-的位置,转换后偏移6对应原始5
                actualOffset <= 12 -> actualOffset - 2
                else -> trimmed.length
            }
            // 确保原始偏移不超过输入文本的实际长度
            return originalOffset.coerceAtMost(trimmed.length)
        }
    }

    return TransformedText(annotatedString, phoneNumberOffsetTranslator)
}

关键修改点

  1. originalToTransformed:

    • 用coerceAtMost限制原始偏移不超过输入文本长度
    • 偏移超出输入范围时,返回转换后文本的实际长度,而非固定的12
  2. transformedToOriginal:

    • 限制转换后的偏移不超过转换后文本长度
    • 调整条件判断,适配添加-后的位置对应关系
    • 最后用coerceAtMost确保返回的原始偏移不超过输入文本长度,避免空输入时返回无效值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 01:53:29