TextView 上可以设置链接,可以自定义点击事件,但设置多个就比较麻烦了,这里写了个简单的工具方法设置多项点击,并把链接的下划线去掉。
public final class TextHelper {
/**
* 将文字转成连接,可以点击,产生点击事件.
* 定义格式为 [show text],为链接, 点击事件的key为从0开始的链接的次序.
* <br/>
* 如果需要多次添加span,这个应该放在第一个转义.后面再做imageSpan等操作.
*
* @param source 待转义的字符.
* @return
*/
public static Spannable getLinkSpan(int color, CharSequence source, WpClickSpan.OnSpanClickListener listener) {
SpannableStringBuilder ssb = new SpannableStringBuilder(source);
// 1. 找到所有的位置.记录下
// 2. 替换掉格式[], 转成要显示的文本
// 3. 添加点击span.添加事件.
Pattern pattern = Pattern.compile("\\[.+?\\]");
final Matcher matcher = pattern.matcher(source);
int offset = 0;
//存放所有的链接起始点和终点位置z
//这里需要注意的是每替换一次会有2个位置的偏移
List<Integer> indexArray = new ArrayList<>();
while (matcher.find()) {
String group = matcher.group();
int start = matcher.start() - offset;
int end = matcher.end() - offset;
//每次移除一对[]都有2个偏移.
ssb.replace(start, end, group.substring(1, group.length() - 1));
indexArray.add(start);
indexArray.add(end - 2);
offset += 2;
}
//indexArray
for (int i = 0; i < indexArray.size(); i += 2) {
int start = indexArray.get(i);
int end = indexArray.get(i + 1);
final WpClickSpan clickSpan = new WpClickSpan(1 + i / 2,color, listener);
ssb.setSpan(clickSpan, start, end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
}
return ssb;
}
根据text,获取到span。链接文字要放在中括号里,可以设置链接字的颜色。设置点击是通过自定义的ClickSpan实现的。
public class WpClickSpan extends ClickableSpan implements ParcelableSpan {
private int mKey;//连接key,用于确定唯一的链接点击
private int mColor;
OnSpanClickListener spanClickListener;
public WpClickSpan(int key, int color, OnSpanClickListener spanClickListener) {
this.mKey = key;
mColor = color;
this.spanClickListener = spanClickListener;
}
public void setSpanClickListener(OnSpanClickListener spanClickListener) {
this.spanClickListener = spanClickListener;
}
@Override
public void onClick(View widget) {
if (spanClickListener != null) {
spanClickListener.onClick(widget, mKey);
}
}
@Override
public int getSpanTypeId() {
return 11;//@hide TextUtils.URL_SPAN;
}
public int getSpanTypeIdInternal(){
return 0;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mColor);
}
/**
* Makes the text underlined and in the link color.
*/
@Override
public void updateDrawState(TextPaint ds) {
ds.setColor(mColor);
// ds.setUnderlineText(true);
}
public interface OnSpanClickListener {
void onClick(View widget, int key);
}
}
这里 ds.setUnderlineText(true)就可以加入下划线了。
然后就是使用了:
Spannable s = TextHelper.getLinkSpan(getResources().getColor(R.color.color_c9), getResources().getString(R.string.nav_has_read), new WpClickSpan.OnSpanClickListener() {
@Override
public void onClick(View widget, int key) {
if (key == 1) {
//to do
} else if (key == 2) {
// to do
}
}
});
TextView tv = (TextView) root.findViewById(R.id.nav_text);
tv.setText(s);
tv.setMovementMethod(LinkMovementMethod.getInstance());