今回はTextView!
半日悩んで解決したのでメモです。
条件
- TextViewに複数のURLが含まれる可能性がある。
- そのテキストは自分以外のだれかが入力したもので、HTMLフォーマット化されていない。
- そのURLに関して正しいかどうかを判断するロジックはGoodleさんに任せる。
- それぞれのURLごとに正しいURLに飛ぶこと。
- それぞれのURLをタップしたときに確認ダイアログをつける。
とりあえず簡単なやつから。
まずGoogleさんに判断させる部分だけど、
textView.setAutoLinkMask(Linkify.WEB_URLS);この一行でOK。あとはGoogleさんがよきに計らってくれる。
複数URLがあっても問題なし。HTMLフォーマットも必要なし。
(ただし、複数あるが、連続してしまうとさすがに判別不能。まぁそこは無視。スプリットでもなんでもすればいい。)
大半の条件はこれで満たせるのだけど、これだけでは確認ダイアログが付けられない。
タップするとアプリから勝手にブラウザに飛んで行ってしまう。
それでは条件満たせないので、それぞれのリンクに確認ダイアログをつけることにする。
そしてここから泥沼へ。
それぞれのリンクはURLSpanというオブジェクトとして保管されている。(それすら今回初めて知りました)
このURLSpanのonClickメソッドを継承し、onClickメソッド内でダイアログ表示→OKならブラウザへで完成するはず。
しかし、残念ながら、TextViewのsetTextメソッドはfinalメソッドのため、継承できず、autoLinkの動きをかえることはできません!何か方法があれば教えてください。
ということで苦肉の策。。。
CharSequence text2 = textView.getText();
if( text2 instanceof Spannable ) {
Spannable spannable = (Spannable) text2;
URLSpan[] spans = spannable.getSpans(0, text2.length(), URLSpan.class);
for (URLSpan urlSpan : spans) {
int start = spannable.getSpanStart(urlSpan);
int end = spannable.getSpanEnd(urlSpan);
spannable.removeSpan(urlSpan);
spannable.setSpan(new MyURLSpan(urlSpan.getURL()), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
やってること
- textView.getText()の中身がSpannableであったら、URLSpanを取得する。
- それぞれのURLSpanのスタートとエンドのポジションを取得する。
- そのURLSpanを削除する。
- 同じ場所にMyURLSpanをぶち込む!
全体
MainActivity.java
package com.example.textviewsample;import android.app.Activity;
import android.os.Bundle;
import android.text.Spannable;
import android.text.Spanned;
import android.text.style.URLSpan;
import android.text.util.Linkify;
import android.view.Menu;
import android.widget.TextView;public class MainActivity extends Activity {
private static final String text = "やふる:http://yahoo.co.jp\nぐぐる:http://www.google.co.jp\nびんぐる:http://www.bing.com/";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = (TextView)this.findViewById(R.id.textview);
textView.setAutoLinkMask(Linkify.WEB_URLS);
textView.setText(text);
CharSequence text2 = textView.getText();
if( text2 instanceof Spannable ) {
Spannable spannable = (Spannable) text2;
URLSpan[] spans = spannable.getSpans(0, text2.length(), URLSpan.class);
for (URLSpan urlSpan : spans) {
int start = spannable.getSpanStart(urlSpan);
int end = spannable.getSpanEnd(urlSpan);
spannable.removeSpan(urlSpan);
spannable.setSpan(new MyURLSpan(urlSpan.getURL()), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}}
MyURLSpan.java
package com.example.textviewsample;import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Parcel;
import android.text.style.URLSpan;
import android.view.View;public class MyURLSpan extends URLSpan {
public MyURLSpan(Parcel src) {
super(src);
}public MyURLSpan(String url) {
super(url);
}@Override
public void onClick(final View widget) {
AlertDialog.Builder builder = new AlertDialog.Builder(widget.getContext());
builder.setTitle("確認");
builder.setMessage(getURL()+"へ飛びますか?");
builder.setPositiveButton("おっけー", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
onClickSuper(widget);
}
});
builder.setNegativeButton("やだ", null);
builder.show();
}
private void onClickSuper(View widget) {
super.onClick(widget);
}
}
activity_main.xml
何が驚いたって、textView.getText()がString以外のもの返すこと。
CharSequenceのことを全く気にせずStringしか使ってこなかった自分が恥ずかしい。
MyURLSpan込みのTextViewを作成してみたい!がんばる。
今日はここまで。