前提:之前遇到過一次textview顯示url的方式策彤,但是并未深入探究愁拭。但是讲逛,上個禮拜一個朋友問我如何在textview上面加載url,并且點(diǎn)擊跳轉(zhuǎn)到指定頁面岭埠。當(dāng)時(shí)對這個比較感興趣也就深入探究了一番盏混。雖然實(shí)現(xiàn)了蔚鸥,但是效果并不理想。如果哪位看官對這一點(diǎn)许赃,理解的比較深入止喷,請告訴我一聲,謝謝了混聊。
首先
- 對TextView屬性比較熟悉的開發(fā)者應(yīng)該都知道TextView有一個叫做autoLink的屬性弹谁,可以將符合指定格式的文本轉(zhuǎn)換為可單擊的超鏈接形式,在幫助文檔中也可以發(fā)現(xiàn)Android給我們提供了如下幾種格式:
1句喜、none:表示不進(jìn)行任何匹配预愤,默認(rèn);
2咳胃、Web:表示匹配Web Url植康, 如: 連接地址為http://www.baidu.com會成為可單擊跳轉(zhuǎn)的超鏈接;
3展懈、Email:表示匹配郵件地址销睁, 如:郵件地址為xx@sina.com會成為可單擊的超鏈接;
4标沪、Phone:表示匹配電話號碼榄攀,如:點(diǎn)擊號碼10000會跳到撥號界面;
5金句、Map:表示匹配地圖地址檩赢;
6、All:表示將會匹配web违寞、email贞瞒、phone、map趁曼;
如下圖所示
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_margin="16dp"
android:text="123"
android:autoLink="phone"/>
- 其中android:autoLink=" "就是加載的屬性
其次
- 要實(shí)現(xiàn)點(diǎn)擊textview中url的跳轉(zhuǎn)到指定功能頁面的功能军浆,有這樣兩種功能
1、直接跳轉(zhuǎn)到指定頁面(可以直接自定義頁面)挡闰;
2乒融、通過手機(jī)瀏覽器到指定頁面
首先,來看跳轉(zhuǎn)到指定頁面的寫法
public class MainActivity extends AppCompatActivity {
TextView mTxtWeb;
CharSequence mContent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
/**
* 初始化控件
*/
private void initView() {
mTxtWeb = (TextView) findViewById(R.id.txt_web);
String htmlLinkText = "天下"+"www.google.com"+"為公";
mTxtWeb.setText(Html.fromHtml(htmlLinkText));
mTxtWeb.setMovementMethod(LinkMovementMethod.getInstance());
CharSequence text = mTxtWeb.getText();
if (text instanceof Spannable) {
int end = text.length();
Spannable sp = (Spannable) mTxtWeb.getText();
URLSpan[] urls = sp.getSpans(0, end, URLSpan.class);
SpannableStringBuilder style = new SpannableStringBuilder(text);
style.clearSpans();
for (final URLSpan url : urls) {
//最主要的一點(diǎn)
CustomClickUrlSpan myURLSpan = new CustomClickUrlSpan(url.getURL(), new CustomClickUrlSpan.OnLinkClickListener() {
@Override
public void onLinkClick(View view) {
Intent intent= new Intent(this,WebActivity.class);
intent.putExtra("url",url.getURL());
startActivity(intent);
}
});
style.setSpan(myURLSpan, sp.getSpanStart(url), sp.getSpanEnd(url), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
mTxtWeb.setText(style);
}
}
-
其中CustomClickUrlSpan,是點(diǎn)擊url跳轉(zhuǎn)摄悯,其中傳入一個url赞季,一個自定義接口,達(dá)到跳轉(zhuǎn)到指定頁面的目的奢驯。
public class CustomClickUrlSpan extends ClickableSpan { private String url; private OnLinkClickListener mListener; public CustomClickUrlSpan(String url, OnLinkClickListener listener) { this.url=url; this.mListener=listener; } @Override public void onClick(View widget) { if (mListener!=null){ mListener.onLinkClick(widget); } } /** * 跳轉(zhuǎn)鏈接接口 */ public interface OnLinkClickListener{ void onLinkClick(View view); } }
-
其中ClicableSpan是系統(tǒng)的方法申钩,其中定義了一個抽象點(diǎn)擊的方法(來看看系統(tǒng)源碼)
public abstract class ClickableSpan extends CharacterStyle implements UpdateAppearance { private static int sIdCounter = 0; private int mId = sIdCounter++; /** * Performs the click action associated with this span. * 這個是點(diǎn)擊方法 */ public abstract void onClick(View widget); /** * Makes the text underlined and in the link color. */ @Override public void updateDrawState(TextPaint ds) { //這個是設(shè)置url顏色 ds.setColor(ds.linkColor); //這個是設(shè)置是否有下劃線 ds.setUnderlineText(true); } /** * Get the unique ID for this span. * * @return The unique ID. * @hide */ public int getId() { return mId; } }
-
當(dāng)然也有簡單的寫法,比如:
/** * 點(diǎn)擊跳轉(zhuǎn) */ private class MyURLSpan extends ClickableSpan { private String mUrl; MyURLSpan(String url) { mUrl = url; } @Override public void onClick(View widget) { Toast.makeText(MainActivity.this, mContent.toString(), Toast.LENGTH_LONG).show(); } }
第二種用的內(nèi)部類的方法瘪阁,但是會有局限性撒遣,會讓主頁變得太繁瑣邮偎,也會讓跳轉(zhuǎn)受限,為了讓代碼看著清晰簡潔义黎,所以推薦使用第一種方法禾进。(個人理解,不對的還請指正)
其次轩缤,通過瀏覽器跳轉(zhuǎn)到指定頁面(并取消下劃線)
public class CustomUrlSpan extends UnderlineSpan implements Parcelable {
String url;
public CustomUrlSpan(String url) {
this.url = url;
}
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
if (ds != null) {
ds.setUnderlineText(false);
}
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.url);
}
protected CustomUrlSpan(Parcel in) {
super(in);
this.url = in.readString();
}
public static final Creator<CustomUrlSpan> CREATOR = new Creator<CustomUrlSpan>() {
public CustomUrlSpan createFromParcel(Parcel source) {
return new CustomUrlSpan(source);
}
public CustomUrlSpan[] newArray(int size) {
return new CustomUrlSpan[size];
}
};
}
-
一定要實(shí)現(xiàn)Parcelable接口命迈,要不會有錯誤提示(下面是activity中的用法贩绕,其中通過瀏覽器跳轉(zhuǎn)到指定頁面火的,并且取消了下劃線)。
/** * 初始化控件 */ private void initView() { mTxtWeb = (TextView) findViewById(R.id.txt_web); String htmlLinkText = "天下"+"www.google.com"+"為公"; mTxtWeb.setText(Html.fromHtml(htmlLinkText)); mTxtWeb.setMovementMethod(LinkMovementMethod.getInstance()); CharSequence text = mTxtWeb.getText(); if (text instanceof Spannable) { int end = text.length(); Spannable sp = (Spannable) mTxtWeb.getText(); URLSpan[] urls = sp.getSpans(0, end, URLSpan.class); SpannableStringBuilder style = new SpannableStringBuilder(text); style.clearSpans(); for (final URLSpan url : urls) { CustomUrlSpan myURLSpan = new CustomUrlSpan(url.getURL()); style.setSpan(myURLSpan, sp.getSpanStart(url), sp.getSpanEnd(url), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } mTxtWeb.setText(style); } }
最后(還有一點(diǎn)比較困惑)
- UnderlineSpan和ClickableSpan都有設(shè)置取消下劃線的方法(updateDrawState)淑倾,重寫了方法之后馏鹤,UnderlineSpan取消了下劃線,但是ClickableSpan卻取消不了這一點(diǎn)比較困惑娇哆。
- 看源碼可以看到UnderlineSpan和ClickableSpan都是繼承CharacterStyle湃累,并且有一個抽象方法updateDrawState(),那么直接繼承CharacterStyle碍讨,然后再自定義一個跳轉(zhuǎn)接口可否實(shí)現(xiàn)跳轉(zhuǎn)到指定接口呢治力,經(jīng)過試驗(yàn)之后還是會有些許不盡如人意。如果哪位仁兄對這一點(diǎn)比較了解勃黍,還請告訴我一聲宵统,不勝感激。
感悟
對于我們來說覆获,不管做什么事情應(yīng)該盡自己最大努力去做好马澈,事事都怕認(rèn)真二字
引用知乎上面的一段話就是:
如果天空是黑暗的,那就摸黑生存弄息;如果發(fā)出聲音是危險(xiǎn)的痊班,那就保持沉默;如果自覺無力發(fā)光的摹量,那就蜷伏于墻角涤伐。但不要習(xí)慣了黑暗就為黑暗辯護(hù);不要為自己的茍且而得意缨称;不要嘲諷那些比自己更勇敢熱情的人們凝果。我們可以卑微如塵土,不可扭曲如蛆蟲具钥《勾澹——季業(yè)推薦一個探討技術(shù)的技術(shù)群(493180098)