最近在寫案子的時候遇到一個需求, 希望 textView 能夠偵測 http:// 並且判斷該url為何,並根據不同的url做不同的動作,假設只需要判斷 hyperlink 使用 textview 內建的android:autolink就可以完成,但是內建的textView並不能偵測click的動作,所有的hyperlink都會自動導向browser ,這並符合我們的需求,經過了一段時間的尋找,總算找到了解法,在這邊跟大家分享。
使用的原理
由於 textview 可以使用 SpannableString 然而 SpannableString 有個method 叫 setSpan ,而setSpan的
第一個參數可以傳各式各樣的Span,其中有一個叫做 ClickableSpan ,使用這個span讓我們可以接收到click event, 但是要使hyperlink可以點擊還必須多做一道手續,setMoveMentMethod 在設定完成之後,我們的功能就算大功告成了。
程式碼範例
public void seTextLinkClickListener(TextLinkClickListener listener) { mListener = listener; MovementMethod m = getMovementMethod(); if ((m == null) || !(m instanceof LinkMovementMethod)) { if (getLinksClickable()) { setMovementMethod(LinkMovementMethod.getInstance()); } } } public void GenerateLink(String text) { SpannableString linkableText = new SpannableString(text); gatherLinks(listOfLinks, linkableText, hyperLinksPattern); for(int i = 0; i< listOfLinks.size(); i++) { Hyperlink linkSpec = listOfLinks.get(i); linkableText.setSpan(linkSpec.span, linkSpec.start, linkSpec.end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } setText(linkableText); } private final void gatherLinks(ArrayList<Hyperlink> links, Spannable s, Pattern pattern) { Matcher m = pattern.matcher(s); while (m.find()) { int start = m.start(); int end = m.end(); Hyperlink spec = new Hyperlink(); spec.textSpan = s.subSequence(start, end); spec.span = new InternalURLSpan(spec.textSpan.toString()); spec.start = start; spec.end = end; links.add(spec); } } public class InternalURLSpan extends ClickableSpan { private String clickedSpan; public InternalURLSpan (String clickedString) { clickedSpan = clickedString; } @Override public void onClick(View textView) { mListener.onTextLinkClick(textView, clickedSpan); } } class Hyperlink { CharSequence textSpan; InternalURLSpan span; int start; int end; }
接著只需要再mainActivity裡面使用這個檔案就可以了
附上 sample code
網路上也有相關的Git Project
沒有留言:
張貼留言