最近项目中遇到一个问题,就是一段文字中股票可点击并跳到电话,只记得SpannableString可以实现富文本功能,但并不知道可实现的富文本有点击功能,就开始借助万能搜索引擎,结果不出意料,的确有ClickableSpan这个类可实现点击功能,于是就开始查找Android api ClickableSpan,废话不说了上代码
TextView tv = (TextView) findViewById(R.id.tv_other_report);
String content = "This is a text,click me" ;
SpannableString spannableString = new SpannableString(content);
spannableString.setSpan(new Clickable(v -> {
//做点击需要的事情
}), start, end,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setMovementMethod(LinkMovementMethod.getInstance());//必须设置否则无法点击
tv.setHighlightColor(getResources().getColor(android.R.color.transparent));//不设置该属性,点击后会有背景色
tv.setText(spannableString);复制代码
下面设置点击事件的监听
/**
* 内部类,用于截获点击富文本后的事件
*/
class Clickable extends ClickableSpan implements View.OnClickListener {
private final View.OnClickListener mListener;
public Clickable(View.OnClickListener mListener) {
this.mListener = mListener;
}
@Override
public void onClick(View v) {
mListener.onClick(v);
}
@Override
public void updateDrawState(TextPaint ds) {
//设置点击区域的颜色
ds.setColor(getResources().getColor(R.color.back_text_color_selector));
ds.setUnderlineText(false); //去除超链接的下划线
ds.clearShadowLayer();//清除阴影
}
}复制代码
如何设置文字点击色
private class LinkTouchMovementMethod extends LinkMovementMethod {
private TouchableSpan mPressedSpan;
@Override
public boolean onTouchEvent(TextView textView, Spannable spannable, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mPressedSpan = getPressedSpan(textView, spannable, event);
if (mPressedSpan != null) {
mPressedSpan.setPressed(true);
Selection.setSelection(spannable, spannable.getSpanStart(mPressedSpan),
spannable.getSpanEnd(mPressedSpan));
}
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
TouchableSpan touchedSpan = getPressedSpan(textView, spannable, event);
if (mPressedSpan != null && touchedSpan != mPressedSpan) {
mPressedSpan.setPressed(false);
mPressedSpan = null;
Selection.removeSelection(spannable);
}
} else {
if (mPressedSpan != null) {
mPressedSpan.setPressed(false);
super.onTouchEvent(textView, spannable, event);
}
mPressedSpan = null;
Selection.removeSelection(spannable);
}
return true;
}
private TouchableSpan getPressedSpan(TextView textView, Spannable spannable, MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= textView.getTotalPaddingLeft();
y -= textView.getTotalPaddingTop();
x += textView.getScrollX();
y += textView.getScrollY();
Layout layout = textView.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
TouchableSpan[] link = spannable.getSpans(off, off, TouchableSpan.class);
TouchableSpan touchedSpan = null;
if (link.length > 0) {
touchedSpan = link[0];
}
return touchedSpan;
}
}复制代码
这需要将应用到 TextView 像这样:
yourTextView.setMovementMethod(new LinkTouchMovementMethod());
这是编辑基于由 LinkTouchMovementMethod 设置的按下状态的绘制状态修改的 ClickableSpan: (它也会删除下划线的链接)
public abstract class TouchableSpan extends ClickableSpan {
private boolean mIsPressed;
private int mPressedBackgroundColor;
private int mNormalTextColor;
private int mPressedTextColor;
public TouchableSpan(int normalTextColor, int pressedTextColor, int pressedBackgroundColor) {
mNormalTextColor = normalTextColor;
mPressedTextColor = pressedTextColor;
mPressedBackgroundColor = pressedBackgroundColor;
}
public void setPressed(boolean isSelected) {
mIsPressed = isSelected;
}
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setColor(mIsPressed ? mPressedTextColor : mNormalTextColor);
ds.bgColor = mIsPressed ? mPressedBackgroundColor : 0xffeeeeee;
ds.setUnderlineText(false);
}
}复制代码