这个问题是由于系统原因引发,目前发现在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 上的其他解决方案。

更多相关文章

  1. H5 调用android原生相机代码分析
  2. android 逆向工程-工具篇 jadx(九)
  3. 浅入浅出Android(007):看看你的手机上有哪些传感器
  4. Android多渠道打包方案
  5. android的Fragment解析(一行代码引发的思考)
  6. Android(安卓)Dialog 示例
  7. Android(安卓)学习之《第一行代码》第二版 笔记(十九)从相册中选取
  8. 《第一行代码Android》学习总结第十章 Service实践——下载功能
  9. android 设置全屏方法1

随机推荐

  1. 为什么我写的Android闹钟到时间时却不会
  2. Android实现拨号器电话
  3. Android(安卓)学习 笔记_12. Spinner的简
  4. 在Fragment中使用BaiduMap SDK
  5. SQlite Android数据库的应用 Android SQL
  6. NDK Stack
  7. Android 显示隐藏状态栏
  8. android中横竖屏切换状态保持一致
  9. android原生分享图片失败的问题
  10. android的一些自定义控件