Android(安卓)4.1/4.1.1 TextView.setText for Html 引发ArrayIndexOutOfBoundsException的问题
16lz
2021-01-26
这个问题是由于系统原因引发,目前发现在android4.1、4.1.1的系统版本上,测试机器Samsung galaxy note 2(模拟器)。
目前网上讨论的方案大多是直接捕捉异常重新设置setText(text.toString());
代码如下:
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { try { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } catch (IndexOutOfBoundsException e) { setText(getText().toString()); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } @Override public void setGravity(int gravity) { try { super.setGravity(gravity); } catch (IndexOutOfBoundsException e) { setText(getText().toString()); super.setGravity(gravity); } }@Overridepublic void setText(CharSequence text, BufferType type) { try { super.setText(text, type); } catch (IndexOutOfBoundsException e) { setText(text.toString()); } } }
这种方式可以解决崩溃的问题,但是imagespan却展示不出来。
第二种方案:删除引发问题的span。
代码如下:
@Overridepublic void setText(CharSequence text, BufferType type) { try { super.setText(text, type); } catch (IndexOutOfBoundsException e) { if (text instanceof Spanned) { Spanned spanned = (Spanned) text; SpannableStringBuilder builder = new SpannableStringBuilder(spanned); MetricAffectingSpan[] spans = spanned.getSpans(0, spanned.length(), MetricAffectingSpan.class); if (spans != null && spans.length > 0) { for (MetricAffectingSpan span : spans) { if (span instanceof ImageSpan) { //do nothing } else { builder.removeSpan(span); } } } super.setText(builder, type); } } }
这种方案可以防止崩溃,而且可以使imagespan继续展示,只是删除了其他span。
第三种方案:在引发问题span的前后加入空格符。
代码如下:
@Overridepublic void setText(CharSequence text, BufferType type) { try { super.setText(text, type); } catch (IndexOutOfBoundsException e) { if (text instanceof Spanned) { Spanned spanned = (Spanned) text; SpannableStringBuilder builder = new SpannableStringBuilder(spanned); MetricAffectingSpan[] spans = spanned.getSpans(0, spanned.length(), MetricAffectingSpan.class); if (spans != null && spans.length > 0) { for (MetricAffectingSpan span : spans) { int spanStart = builder.getSpanStart(span); if (isNotSpace(builder, spanStart - 1)) { builder.insert(spanStart, " "); } int spanEnd = builder.getSpanEnd(span); if (isNotSpace(builder, spanEnd)) { builder.insert(spanEnd, " "); } } } super.setText(builder, type); } } }private boolean isNotSpace(CharSequence text, int where) { return where < 0 || where >= text.length() || text.charAt(where) != ' '; }
这种方案相对于1,2相对完美,并不会去除span,内容风格可以保留。
在此感谢国外大神提供思路(issues 35466的第25楼):
https://code.google.com/p/android/issues/detail?id=35466
不能完全解决问题的同学可以参考该issues 上的其他解决方案。
更多相关文章
- H5 调用android原生相机代码分析
- android 逆向工程-工具篇 jadx(九)
- 浅入浅出Android(007):看看你的手机上有哪些传感器
- Android多渠道打包方案
- android的Fragment解析(一行代码引发的思考)
- Android(安卓)Dialog 示例
- Android(安卓)学习之《第一行代码》第二版 笔记(十九)从相册中选取
- 《第一行代码Android》学习总结第十章 Service实践——下载功能
- android 设置全屏方法1