TextView使用ClickableSpan崩溃问题¶
报错信息
android.view.InflateException: Binary XML file line #14: Error inflating class TextView
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:767)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:810)
at android.view.LayoutInflater.inflate(LayoutInflater.java:508)
at android.view.LayoutInflater.inflate(LayoutInflater.java:418)
bugly将它归类为 java.lang.ArrayIndexOutOfBoundsException
。
item的layout没有设置ellipsize
和maxLine
。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="2dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="4dp"
android:background="@color/compPageBgColor"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/en_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start"
android:textSize="16sp" />
<TextView
android:id="@+id/cn_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start"
android:textSize="13sp" />
</LinearLayout>
在RecyclreView创建ViewHodler的时候就会崩溃。onBindViewHolder
中,textview
使用了ClickableSpan。
ClickableSpan复写了updateDrawState
方法。
int color = Color.RED;
public CVH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new CVH(LayoutInflater.from(parent.getContext()).inflate(R.layout.my_item, parent, false));
}
@Override
public void onBindViewHolder(@NonNull CVH holder, int position) {
SpannableStringBuilder ssb = new SpannableStringBuilder("abcdefg");
// ...
ssb.setSpan(new ClickableSpan() {
@Override
public void onClick(@NonNull View widget) {
if (onItemClickListener != null) {
onItemClickListener.onClick(info);
}
}
@Override
public void updateDrawState(TextPaint ds) {
if (ds != null) {
ds.setColor(color);
ds.setUnderlineText(true);
}
}
}, start, end, Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
holder.contentEnTv.setMovementMethod(LinkMovementMethod.getInstance());
holder.contentEnTv.setText(ssb);
}
将TextView换成androidx.appcompat.widget.AppCompatTextView,一样会崩溃
问题会出现在
- 小米4c(Android5.1.1, API 22)
- OPPO(Android 6.0.1, API 23)
- 安卓平板(Android 7)
没有这个崩溃的机型,红米6A(Android8.1),1+5(Android 10)。
相关问题: https://stackoverflow.com/questions/46947850/textview-with-ellipsize-middle-casues-arrayindexoutofboundsexception-exception
Android系统(7及以下)的一个bug https://issuetracker.google.com/issues/36950033
绕过这个问题¶
Android7以上的系统不会出现此bug,我们尝试绕过这个问题。 textView设置span的代码需要修改。
新增一个抽象类ColorClickSpan
。里面有一个颜色值。
public abstract class ColorClickSpan extends ClickableSpan {
private int color;
public ColorClickSpan(int color) {
this.color = color;
}
@Override
public void updateDrawState(TextPaint ds) {
if (ds != null) {
ds.setColor(color);
ds.setUnderlineText(true);
}
}
}
修改onBindViewHolder
里的使用方式。
ssb.setSpan(new ColorClickSpan(color) {
@Override
public void onClick(View widget) {
// ...
}
}, start, end, Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
这样改,小米4c(5.1.1)和平板(7)可以正常使用了。
小结一下,最开始是为了解决ForegroundColorSpan失效的问题。想用ClickableSpan同时实现点击和显示颜色的功能。 却触发了低版本安卓系统TextView的bug。调整了实现方式后,绕开了这个低版本安卓系统崩溃问题。
本站说明
一起在知识的海洋里呛水吧。广告内容与本站无关。如果喜欢本站内容,欢迎投喂作者,谢谢支持服务器。如有疑问和建议,欢迎在下方评论~