一段文字中包含@简书 的特殊字符串,该字符串带特殊前景色和特殊点击事件
SpannableStringBuilder style = new SpannableStringBuilder(text);
int textColor = textView.getContext().getResources().getColor(R.color.theme);
int highlightColor = textView.getContext().getResources().getColor(R.color.transparent);
if (onSpanClickCommand != null) {
//SPAN_EXCLUSIVE_EXCLUSIVE:标识在Span范围内的文本前后输入新的字符时是否把它们也应用这个效果
style.setSpan(new ClickableSpan() {
@Override
public void onClick(@NonNull View widget) {
onSpanClickCommand.execute();
}
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.setColor(textColor);
ds.setUnderlineText(false);
}
}, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else {
style.setSpan(new ForegroundColorSpan(textColor), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
//设置textView中所有文字为spannable格式
textView.setText(style);
//启用上面为每个字绑定的ClickableSpan
//TextViewSpanClickableMovementMethod里解决了TextView “无ClickableSpan事件” 文案无点击事件BUG
textView.setMovementMethod(TextViewSpanClickableMovementMethod.getInstance());
//去掉点击Span的背景
textView.setHighlightColor(highlightColor);
问题来了:@简书 的点击事件有了,其他文字的点击事件没了
解决方案:
继承LinkMovementMethod,重新onTouchEvent方法,当点击未设置ClickableSpan事件的文字时,super.onTouchEvent中返回的Boolean值为false,此时就可以执行OnClickListener事件
1、可以拿到TextView父控件中的事件,直接执行
2、getInstance方法中传入需要执行的OnClickListener事件,在onTouchEvent中执行
public class TextViewSpanClickableMovementMethod extends LinkMovementMethod {
private static TextViewSpanClickableMovementMethod instance;
public static TextViewSpanClickableMovementMethod getInstance() {
if (instance == null) {
instance = new TextViewSpanClickableMovementMethod();
}
return instance;
}
@Override
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
boolean b = super.onTouchEvent(widget, buffer, event);
//当TextView中某段文字没有设置ClickableSpan事件的时候,b返回false,此时点击这段文字,响应父类事件
if (!b && event.getAction() == MotionEvent.ACTION_UP) {
ViewParent parent = widget.getParent();
if (parent instanceof ViewGroup) {
return ((ViewGroup) parent).performClick();
}
}
return b;
}
}