【Android】textview识别并展示网址路径,可点击跳转打开链接

///textview识别并展示网址链接,并可点击进行跳转
public class SpanUtils {

    private Context mContext;
    private static volatile SpanUtils uniqueInstance;
    public SpanUtils(Context mContext) {
        this.mContext = mContext;
    }
    //采用Double CheckLock(DCL)实现单例
    public static SpanUtils getInstance(Context context) {
        if (uniqueInstance == null) {
            synchronized (LocationUtils.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new SpanUtils(context);
                }
            }
        }
        return uniqueInstance;
    }
    /**
     * 拦截超链接
     * @param tv
     */
    public void interceptHyperLink(TextView tv) {
        tv.setMovementMethod(LinkMovementMethod.getInstance());
        CharSequence text = tv.getText();
        SpannableStringBuilder stringBuilder=identifyUrl(text);
        tv.setText(stringBuilder);
    }
    LinkedList<String> mStringList = new LinkedList<String>();
    LinkedList<UrlInfo> mUrlInfos = new LinkedList<UrlInfo>();
    private String pattern =
            "((http|ftp|https)://)(([a-zA-Z0-9\\._-]+\\.[a-zA-Z]{2,6})|([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}))(:[0-9]{1,4})*(/[a-zA-Z0-9\\&%_\\./-~-]*)?|(([a-zA-Z0-9\\._-]+\\.[a-zA-Z]{2,6})|([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}))(:[0-9]{1,4})*(/[a-zA-Z0-9\\&%_\\./-~-]*)?";

    Pattern r = Pattern.compile(pattern);
    Matcher m;
    int flag= Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;

    class UrlInfo {
        public int start;
        public int end;
    }


    public SpannableStringBuilder identifyUrl(CharSequence text) {
        mStringList.clear();
        mUrlInfos.clear();

        CharSequence contextText;
        CharSequence clickText;
        text = text == null ? "" : text;
        contextText = text;
        clickText = null;
        m = r.matcher(contextText);
        //匹配成功
        while (m.find()) {
            //得到网址数
            UrlInfo info = new UrlInfo();
            info.start = m.start();
            info.end = m.end();
            mStringList.add(m.group());
            mUrlInfos.add(info);
        }
        return joinText(clickText, contextText);
    }

    /** 拼接文本 */
    private SpannableStringBuilder joinText(CharSequence clickSpanText,
                                                      CharSequence contentText) {
        SpannableStringBuilder spanBuilder;
        if (clickSpanText != null) {
            spanBuilder = new SpannableStringBuilder(clickSpanText);
        } else {
            spanBuilder = new SpannableStringBuilder();
        }
        if (mStringList.size() > 0) {
            //只有一个网址
            if (mStringList.size() == 1) {
                String preStr = contentText.toString().substring(0, mUrlInfos.get(0).start);
                spanBuilder.append(preStr);
                String url = mStringList.get(0);
                CustomUrlSpan customUrlSpan = new CustomUrlSpan(mContext,url);
                int start = spanBuilder.length();
                spanBuilder.append(url, new UnderlineSpan(), flag);
                int end = spanBuilder.length();
                if (start >= 0 && end > 0 && end > start) {
                    spanBuilder.setSpan(customUrlSpan, start, end, flag);
                }
                String nextStr = contentText.toString().substring(mUrlInfos.get(0).end);
                spanBuilder.append(nextStr);
            } else {
                //有多个网址
                for (int i = 0; i < mStringList.size(); i++) {
                    String url = mStringList.get(i);
                    CustomUrlSpan customUrlSpan = new CustomUrlSpan(mContext,url);
                    if (i == 0) {
                        //拼接第1个span的前面文本
                        String headStr =
                                contentText.toString().substring(0, mUrlInfos.get(0).start);
                        spanBuilder.append(headStr);
                    }
                    if (i == mStringList.size() - 1) {
                        //拼接最后一个span的后面的文本
                        int start = spanBuilder.length();
                        spanBuilder.append(mStringList.get(i), new UnderlineSpan(), flag);
                        int end = spanBuilder.length();
                        if (start >= 0 && end > 0 && end > start) {
                            spanBuilder.setSpan(customUrlSpan, start, end, flag);
                        }
                        String footStr = contentText.toString().substring(mUrlInfos.get(i).end);
                        spanBuilder.append(footStr);
                    }
                    if (i != mStringList.size() - 1) {
                        //拼接两两span之间的文本
                        int start = spanBuilder.length();
                        spanBuilder.append(mStringList.get(i), new UnderlineSpan(), flag);
                        int end = spanBuilder.length();
                        if (start >= 0 && end > 0 && end > start) {
                            spanBuilder.setSpan(customUrlSpan, start, end, flag);
                        }
                        String betweenStr = contentText.toString()
                                .substring(mUrlInfos.get(i).end,
                                        mUrlInfos.get(i + 1).start);
                        spanBuilder.append(betweenStr);
                    }
                }
            }
        } else {
            spanBuilder.append(contentText);
        }
        return spanBuilder;
    }

}

///文本框点击超链接功能
public class CustomUrlSpan extends ClickableSpan {

    private Context context;
    private String url;
    public CustomUrlSpan(Context context,String url){
        this.context = context;
        this.url = url;

    }

    @Override
    public void onClick(View widget) {
        // 在这里可以做任何自己想要的处理
        BrowserActivity.start(context, url);
    }
}

参考地址https://www.cnblogs.com/wangqiong/p/10756752.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值