Androidでテキストの中の一部をクリックできるようにする

テキストのなかにhttpとかURLが含まれていて、例えばwebブラウザ上のリンクっぽく、クリックのイベントをひろいたい場合。

URL正規表現
参考:[ヅ] JavaでテキストからURLを抽出する正規表現 (2010-01-13)

private static final Pattern URL_MATCH_PATTERN = Pattern.compile(
       "(http|https):([^\\x00-\\x20()\"<>\\x7F-\\xFF])*",
       Pattern.CASE_INSENSITIVE);


Stringのdescr がテキスト、TextViewのtvDescrが表示したい先 とする。

       // (1) テキストでSpannableString をつくる
       SpannableString spannable = new SpannableString(descr);

       // (2) 対象となる部分を正規表現でさがす
       Matcher matcher = URL_MATCH_PATTERN.matcher(descr);
       while (matcher.find()) {
               // 見つかった部分でClickableSpanを継承したクラスをつくる(下でつくってる)
               UrlClickableSpan span = new UrlClickableSpan(matcher.group());
               // SpannableStringに、マッチした範囲にセットする(だと思う)
               spannable.setSpan(span, matcher.start(), matcher.end(),
                       Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
       }

       // (3) SpannableString をセットする
       tvDescr.setText(spannable);

       // これいる。。。
       tvDescr.setMovementMethod(LinkMovementMethod.getInstance());
// ClickableSpanを継承したクラス。
// onClickの実装のためにいるんだと思う。
class UrlClickableSpan extends ClickableSpan {

       private String url;

       public UrlClickableSpan(String url) {
               super();
               this.url = url;
       }

       @Override
       public void onClick(View v) {
               Uri uri = Uri.parse(this.url);
               Intent intent = new Intent(Intent.ACTION_VIEW, uri);
               startActivity(intent);
       }
}

この例では、onClickのなかでブラウザを読んでいるので結局同じ。

もともとのテキストがhtmlの場合は、簡単にできる。

       tvDescr.setText(Html.fromHtml(descr));


Spannable 系なクラスは、htmlでいうところの「span」な感じで、テキストの一部に何かするときがこれ系だと思われ。めんどくさげなのでまだよくわからない。もっと簡単に出来れば良いのに、という気持ちの壁で。

正規表現もわかっていないのでしんどい。