java.lang.IndexOutOfBoundsException: setSpan (26 ... 26) ends beyond length 10

本文介绍了一个常见的Android开发问题——IndexOutOfBoundsException,并提供了解决方案。当尝试设置的文本跨度超出实际文本长度时,此异常会抛出。文章给出了一个判断文本长度并在安全范围内设置光标位置的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

02-26 18:45:22.793: E/AndroidRuntime(30449): FATAL EXCEPTION: main
02-26 18:45:22.793: E/AndroidRuntime(30449): Process: cn.beeba.app, PID: 30449
02-26 18:45:22.793: E/AndroidRuntime(30449): java.lang.IndexOutOfBoundsException: setSpan (26 ... 26) ends beyond length 10
02-26 18:45:22.793: E/AndroidRuntime(30449):    at android.text.SpannableStringBuilder.checkRange(SpannableStringBuilder.java:1018)
02-26 18:45:22.793: E/AndroidRuntime(30449):    at android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.java:611)
02-26 18:45:22.793: E/AndroidRuntime(30449):    at android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.java:607)
02-26 18:45:22.793: E/AndroidRuntime(30449):    at android.text.Selection.setSelection(Selection.java:76)
02-26 18:45:22.793: E/AndroidRuntime(30449):    at android.text.Selection.setSelection(Selection.java:87)
02-26 18:45:22.793: E/AndroidRuntime(30449):    at android.widget.EditText.setSelection(EditText.java:99)

出现此问题的原因是限制的字符为10,但是字符太长时,就会出现以上错误。
解决办法为:

if (length <= 10) { 
    et_content.setSelection(length); // 将光标移至文字末尾
}
<think>嗯,用户遇到了一个IndexOutOfBoundsException的异常,问题出在设置SpannableString的时候。让我仔细看看他们的代码。他们有一个字符串资源restore_factory_settings_msg,内容是“When you confirm, all the settings of TX and RX will be restored to their default state. Please choose carefully.”。然后他们用SpannableString包装了这个字符串,并尝试设置一个颜色跨度从start到end的位置。但是异常提示说setSpan的范围125到149超过了字符串的长度113。 首先,我需要确认字符串的实际长度。用户提供的字符串原文是英文的,假设没有其他语言环境的影响,直接计算字符数。原句子的长度应该是每个字母、空格和标点都算上。让我数一下:原文中的句子是“When you confirm, all the settings of TX and RX will be restored to their default state. Please choose carefully.”。看起来确实可能超过113个字符吗?或者可能用户在不同的语言环境下有不同的翻译,比如中文,导致实际字符串长度变短? 或者用户在代码中获取字符串时,可能使用了不同的语言资源,比如中文的翻译后的字符串较短,而他们计算start和end的位置时是基于英文原句的长度,导致索引越界。例如,R.string.restore_factory_settings_msg在中文环境下可能被翻译为较短的字符串,比如“确认后,TX和RX的所有设置将被恢复为默认状态,请谨慎选择。”,这样的字符串长度可能只有大约50个字符左右,而用户设置的start和end是125到149,显然超过了实际长度,导致异常。 因此,问题可能出在start和end的值是基于英文原文计算的,而实际运行时加载的是其他语言的翻译,导致长度不足。解决方法应该是动态获取字符串的实际长度,或者在设置span之前检查start和end是否在有效范围内。 另外,用户可能在计算start和end时使用了硬编码的数值,而不是根据字符串内容动态确定位置。例如,他们可能想高亮某个特定的子字符串,比如“restored to their default state”,但使用固定的索引,这在不同的语言版本中会不一致。 正确的做法应该是通过字符串的indexOf方法来动态查找子字符串的起始和结束位置,而不是硬编码。例如,找到“restored”或“default”等关键词的位置,然后设置span的范围,这样即使字符串长度变化,也能正确找到位置。 此外,还应该确保在设置span之前检查start是否小于等于end,并且end不超过字符串的长度。可以添加条件判断,如果超出范围则不设置,或者调整范围到有效区间内。 总结解决步骤: 1. 使用动态方法获取需要高亮部分的起始和结束索引,而不是硬编码。 2. 在设置span之前检查索引是否在有效范围内。 3. 考虑多语言环境下字符串长度的变化,确保代码适应不同翻译的情况。</think>出现该错误的原因是设置的Span范围(125-149)超出了字符串的实际长度(113)。以下是逐步解决方案: **步骤1:获取字符串实际长度** ```kotlin val originalString = context.getString(R.string.restore_factory_settings_msg) val strLength = originalString.length // 先获取实际长度 ``` **步骤2:动态计算需要高亮的位置(推荐)** ```kotlin val targetPhrase = "restored to their default state" val start = originalString.indexOf(targetPhrase) val end = start + targetPhrase.length // 或者如果要高亮"TX and RX" val start = originalString.indexOf("TX and RX") val end = start + "TX and RX".length ``` **步骤3:添加安全校验** ```kotlin if (start >= 0 && end <= strLength) { ss.setSpan(..., start, end, ...) } else { // 处理异常情况 Log.e("SpanError", "Invalid span range: $start-$end") } ``` **步骤4:处理多语言问题** 如果涉及多语言翻译: 1. 确保所有语言版本的字符串都包含目标短语 2. 在不同语言中保持关键短语的一致性 3. 考虑使用占位符: ```xml <string name="restore_msg">%1$s will be reset. Please check</string> ``` ```kotlin val phrase = context.getString(R.string.reset_target) // "TX and RX settings" val fullText = context.getString(R.string.restore_msg, phrase) ``` **错误原因分析:** 当前英文原文字符串长度:113字符 您设置的结束位置:149 实际差异:149 - 113 = 36字符超长 **验证方法:** ```kotlin Log.d("StringDebug", """原始字符串长度:${originalString.length} 目标范围:$start-$end 字符串内容:[${originalString}]""") ``` **完整修正代码:** ```kotlin val originalString = context.getString(R.string.restore_factory_settings_msg) val ss = SpannableString(originalString) val targetPhrase = "TX and RX" // 要强调的部分 val start = originalString.indexOf(targetPhrase) val end = start + targetPhrase.length if (start >= 0 && end <= originalString.length) { ss.setSpan( ForegroundColorSpan(Color.parseColor("#FFD30000")), start, end, Spanned.SPAN_EXCLUSIVE_INCLUSIVE ) } else { // 安全降级处理 Log.w("SpanError", "无法设置高亮:$targetPhrase 未找到") } // 使用ss对象继续后续操作 ``` **预防措施:** 1. 避免硬编码字符串位置 2. 使用`SpannableStringBuilder`处理动态内容 3. 重要位置添加范围校验 4. 使用单元测试验证不同语言版本的字符串格式: ```kotlin @Test fun testRestoreMessageSpan() { val context = ApplicationProvider.getApplicationContext<Context>() val testString = context.getString(R.string.restore_factory_settings_msg) assertTrue("TX and RX" in testString) { "关键短语TX and RX必须存在于所有语言版本中" } val start = testString.indexOf("TX and RX") val end = start + "TX and RX".length assertTrue(end <= testString.length) { "所有语言版本必须包含完整的关键短语" } } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值