Android 8.0点击带EditText的FAB触发IndexOutOfBoundsException问题
Android 8.0上EditText.replace()触发IndexOutOfBoundsException的解决方案
看起来你在Android 8.0(API 26)上碰到了一个针对性的索引越界问题,我来帮你捋捋原因和修复办法。
问题根源分析
从你提供的堆栈跟踪和代码来看,异常是在SpannableStringBuilder.checkRange()中抛出的,对应代码第116行的field.getText().replace(at, at + 1, view.getText())。这说明你尝试替换的文本范围(at到at+1)超出了当前EditText文本的实际长度。
为什么这个问题只在Android 8.0出现?不同版本的Android系统对EditText的光标位置、文本编辑的内部处理逻辑有差异:在8.0上,当EditText的文本已经填满(比如达到你定义的FIELD_LENGTH),或者光标处于文本末尾时,getSelectionStart()返回的值可能等于文本长度,这时候at+1就会超出文本的有效索引范围(索引从0到length-1),触发越界异常。而更高版本的Android可能已经在系统层面做了索引边界的自动修正,所以不会出现这个问题。
修复方案
方案1:添加索引合法性检查,区分替换和追加逻辑
在执行replace操作前,先判断光标位置是否在文本范围内,光标在末尾时直接追加文本而不是替换:
void onClick(TextView view) { if (mFocusGrabber.isFocused()) return; EditText field = getFocusedField(); int at = field.getSelectionStart(); CharSequence inputText = view.getText(); Editable editableContent = field.getText(); int currentTextLength = editableContent.length(); // 检查索引是否合法,避免越界 if (at < currentTextLength) { // 光标在文本中间,替换指定位置的字符 editableContent.replace(at, at + 1, inputText); } else { // 光标在文本末尾,直接追加内容 editableContent.append(inputText); } // 更新光标位置,确保不超出文本长度 int newCursorPos = at + 1; field.setSelection(Math.min(newCursorPos, editableContent.length())); // 原有后续逻辑保持不变 if (field.getSelectionStart() == FIELD_LENGTH) { View next = field.focusSearch(View.FOCUS_RIGHT); if (next != null) { next.requestFocus(); if (next instanceof EditText) { ((EditText) next).setSelection(0); } } } }
方案2:预先修正光标位置的边界
在获取selectionStart后,先做一次边界修正,确保它不会超过文本长度:
void onClick(TextView view) { if (mFocusGrabber.isFocused()) return; EditText field = getFocusedField(); Editable editableContent = field.getText(); int currentTextLength = editableContent.length(); // 修正光标位置,确保在0到currentTextLength之间 int at = Math.max(0, Math.min(field.getSelectionStart(), currentTextLength)); CharSequence inputText = view.getText(); if (at < currentTextLength) { editableContent.replace(at, at + 1, inputText); } else { editableContent.append(inputText); } field.setSelection(Math.min(at + 1, editableContent.length())); // 原有后续逻辑... }
额外建议
你也可以检查一下FIELD_LENGTH的逻辑,确保当EditText文本达到最大长度时,要么禁用数字按钮,要么拦截点击事件,从源头上避免用户在文本已满时继续输入,这样也能减少这类异常的发生。
内容的提问来源于stack exchange,提问作者Fatih
相关产品推荐
相关产品推荐

