Span的多项点击及TextView去下划线

TextView 上可以设置链接,可以自定义点击事件,但设置多个就比较麻烦了,这里写了个简单的工具方法设置多项点击,并把链接的下划线去掉。


public final class TextHelper {


    /**
     * 将文字转成连接,可以点击,产生点击事件.
     * 定义格式为 [show text],为链接, 点击事件的key为从0开始的链接的次序.
     * 
* 如果需要多次添加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 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());


这里要注意两个地方,一个是key是从1开始的,第二个是必须设置setMovementMethod,不然点击事件就没有效果了。

你可能感兴趣的:(Android开发问题系列)