Android 4.1/4.1.1 TextView.setText for Html 引发ArrayIndexOutOfBoundsException的问题

这个问题是由于系统原因引发,目前发现在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);
        }
    }

@Override
public void setText(CharSequence text, BufferType type) {
        try {
            super.setText(text, type);
        } catch (IndexOutOfBoundsException e) {
            setText(text.toString());
            }
        }
    }

这种方式可以解决崩溃的问题,但是imagespan却展示不出来。

第二种方案:删除引发问题的span。
代码如下:

@Override
public 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的前后加入空格符。
代码如下:

@Override
public 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 上的其他解决方案。

当在配置 `:app:debugRuntimeClasspath` 时无法找到 `org.koin:koin-core-ext:4.1.1`,可以尝试以下几种解决方法: ### 检查依赖声明 确保在项目的 `build.gradle`(对于 Groovy DSL)或者 `build.gradle.kts`(对于 Kotlin DSL)文件中正确声明了依赖。 #### Groovy DSL 在 `app` 模块的 `build.gradle` 文件中,检查是否有如下依赖声明: ```groovy dependencies { implementation 'org.koin:koin-core-ext:4.1.1' } ``` #### Kotlin DSL 在 `app` 模块的 `build.gradle.kts` 文件中,检查是否有如下依赖声明: ```kotlin dependencies { implementation("org.koin:koin-core-ext:4.1.1") } ``` ### 检查 Maven 仓库配置 确保项目的 `build.gradle` 或者 `settings.gradle` 文件中配置了正确的 Maven 仓库。Koin 通常可以从 Maven Central 或者 JCenter 下载。 #### Groovy DSL 在项目根目录的 `build.gradle` 文件中,添加如下仓库配置: ```groovy allprojects { repositories { google() mavenCentral() } } ``` #### Kotlin DSL 在项目根目录的 `settings.gradle.kts` 文件中,添加如下仓库配置: ```kotlin dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() } } ``` ### 清理和重建项目 有时候,Gradle 的缓存可能会导致依赖解析问题。可以尝试清理项目并重建: - 在 Android Studio 中,选择 `Build` -> `Clean Project`,然后选择 `Build` -> `Rebuild Project`。 - 或者在终端中,进入项目根目录,执行以下命令: ```bash ./gradlew clean build ``` ### 检查版本号 确保 `4.1.1` 版本的 `koin-core-ext` 确实存在。可以访问 [Maven Central](https://search.maven.org/) 或者 [JCenter](https://bintray.com/) 网站,搜索 `org.koin:koin-core-ext` 来确认该版本是否可用。如果该版本不存在,可以尝试使用其他可用版本。 ### 检查网络连接 确保你的开发环境可以正常访问 Maven 仓库。有时候,网络问题可能会导致依赖下载失败。 ### 检查代理设置 如果你的开发环境使用了代理,确保 Gradle 配置了正确的代理信息。可以在 `gradle.properties` 文件中添加如下配置: ```properties systemProp.http.proxyHost=your.proxy.host systemProp.http.proxyPort=your.proxy.port systemProp.https.proxyHost=your.proxy.host systemProp.https.proxyPort=your.proxy.port ``` 通过以上步骤,应该可以解决配置 `:app:debugRuntimeClasspath` 时无法找到 `org.koin:koin-core-ext:4.1.1` 的问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值