android TextView中識別url


一、需求

     1、在TextView中識別url;

     2、能識別出非http://|https://|ftp://等協議開頭的非標准url

     3、對url設置顏色、下划線、點擊等等

二、方案

 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 SpannableStringBuilderForAllvers identifyUrl(CharSequence text) {
        mStringList.clear();
        mUrlInfos.clear();

        CharSequence contextText;
        CharSequence clickText;
        text = text == null ? "" : text;
        //以下用於拼接本來存在的spanText
        SpannableStringBuilderForAllvers span = new SpannableStringBuilderForAllvers(text);
        ClickableSpan[] clickableSpans = span.getSpans(0, text.length(), ClickableSpan.class);
        if (clickableSpans.length > 0) {
            int start=0;
            int end=0;
            for (int i=0;i<clickableSpans.length;i++){
                start=span.getSpanStart(clickableSpans[0]);
                end=span.getSpanEnd(clickableSpans[i]);
            }
            //可點擊文本后面的內容頁
            contextText = text.subSequence(end, text.length());
            //可點擊文本
            clickText = text.subSequence(start,
                    end);
        } else {
            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 SpannableStringBuilderForAllvers joinText(CharSequence clickSpanText,
                                                      CharSequence contentText) {
        SpannableStringBuilderForAllvers spanBuilder;
        if (clickSpanText != null) {
            spanBuilder = new SpannableStringBuilderForAllvers(clickSpanText);
        } else {
            spanBuilder = new SpannableStringBuilderForAllvers();
        }
        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);
                int start = spanBuilder.length();
                spanBuilder.append(url, new UnderlineSpan(), flag);
                int end = spanBuilder.length();
                if (start >= 0 && end > 0 && end > start) {
                    spanBuilder.setSpan(new ForegroundColorSpan(Color.BLUE), start, end, flag);
                }
                String nextStr = contentText.toString().substring(mUrlInfos.get(0).end);
                spanBuilder.append(nextStr);
            } else {
                //有多個網址
                for (int i = 0; i < mStringList.size(); i++) {
                    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(new ForegroundColorSpan(Color.BLUE), 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(new ForegroundColorSpan(Color.BLUE), 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 SpannableStringBuilderForAllvers extends SpannableStringBuilder{

    public SpannableStringBuilderForAllvers() {
        super("");
    }
    public SpannableStringBuilderForAllvers(CharSequence text) {
        super(text, 0, text.length());
    }
    public SpannableStringBuilderForAllvers(CharSequence text, int start, int end){
        super(text,start,end);
    }

    @Override
    public SpannableStringBuilder append(CharSequence text) {
       if (text == null) {
           return this;
       }
        int length = length();
        return (SpannableStringBuilderForAllvers)replace(length, length, text, 0, text.length());
    }

    /**該方法在原API里面只支持API21或者以上,這里適應低版本*/
    public SpannableStringBuilderForAllvers append(CharSequence text, Object what, int flags) {
        if (text == null) {
            return this;
        }
        int start = length();
        append(text);
        setSpan(what, start, length(), flags);
        return this;
    }
}

 

     

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM