2014年2月10日 星期一

Android 開發 (二十四) handle hyperlink in textView(一)

為何需要客製化  textView 來處理hyperlink

最近在寫案子的時候遇到一個需求, 希望 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

沒有留言:

張貼留言