使用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) }
关键修改点
originalToTransformed:- 用
coerceAtMost限制原始偏移不超过输入文本长度 - 偏移超出输入范围时,返回转换后文本的实际长度,而非固定的12
- 用
transformedToOriginal:- 限制转换后的偏移不超过转换后文本长度
- 调整条件判断,适配添加
-后的位置对应关系 - 最后用
coerceAtMost确保返回的原始偏移不超过输入文本长度,避免空输入时返回无效值
内容的提问来源于stack exchange,提问作者Murphler
相关产品推荐
相关产品推荐

