????下午產(chǎn)品經(jīng)理提了個需求:要在服務(wù)端傳來的文本中用應(yīng)用內(nèi)置瀏覽器打開超鏈接。
去網(wǎng)上搜了下,找到了個方法:
textView.setMovementMethod(LinkMovementMethod.getInstance());
很遺憾,發(fā)現(xiàn)這只是跳轉(zhuǎn)到瀏覽器的方法。
????又看了下網(wǎng)友們的方法,基本都要涉及到SpannableString的設(shè)置;或是自定義UrlSpan,重寫它的onClick方法;有些還要遍歷文本尋找以http開頭的字符串。總之就是很麻煩。
????這些方法很多最后都要用到textView.setText()的方法,但是因為我要解析圖片,這個方法已經(jīng)用掉了,無法重復(fù)使用:
textView.setText(Html.fromHtml(str, new MImageGetter(textView, getApplicationContext()), null));
????所以這些方法都行不通。那行,換種思路,我看看LinkMovementMethod的源碼是怎么實現(xiàn)跳轉(zhuǎn)的。源碼有點長,這里只貼出關(guān)鍵代碼,就是下面的onTouchEvent。
@Override
public boolean onTouchEvent(TextView widget, Spannable buffer,
MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_UP ||
action == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();
x += widget.getScrollX();
y += widget.getScrollY();
Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
link[0].onClick(widget);
} else if (action == MotionEvent.ACTION_DOWN) {
Selection.setSelection(buffer,
buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
}
return true;
} else {
Selection.removeSelection(buffer);
}
}
return super.onTouchEvent(widget, buffer, event);
}
????可以看到,執(zhí)行跳轉(zhuǎn)的語句是在:
if (action == MotionEvent.ACTION_UP) {
link[0].onClick(widget);
}
????這樣就簡單了,我就自定義了一個類WebLinkMethod來繼承LinkMovementMethod 并重寫onTouchEvent()這個方法:
public class WebLinkMethod extends LinkMovementMethod {
private static WebLinkMethod instance;
private Context context;
private WebLinkMethod(Context context) {
this.context = context;
}
public static MovementMethod getInstance(Context context) {
if (instance == null)
instance = new WebLinkMethod(context);
return instance;
}
@Override
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_UP ||
action == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();
x += widget.getScrollX();
y += widget.getScrollY();
Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
// ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
URLSpan[] link = buffer.getSpans(off, off, URLSpan.class);
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
// link[0].onClick(widget);
Intent intent = new Intent(context, H5Activity.class);
intent.putExtra("url", link[0].getURL());
context.startActivity(intent);
} else if (action == MotionEvent.ACTION_DOWN) {
Selection.setSelection(buffer,
buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
}
return true;
} else {
Selection.removeSelection(buffer);
}
}
return super.onTouchEvent(widget, buffer, event);
}
}
????說下幾個改動(代碼中注釋的兩行):
- 由于頁面跳轉(zhuǎn)我們需要用到原頁面的上下文,于是修改了構(gòu)造函數(shù),加入了Context;
- URLSpan是ClickableSpan的子類,實現(xiàn)了getURL()的方法,所以這里要換成它我們才能取到鏈接地址,link[0]就是我們點擊到的超鏈接字符串,通過link[0].getURL()我們可以獲得它的鏈接地址傳給下個頁面;
- 有了上下文context和鏈接地址url,我們就可以把原來的跳轉(zhuǎn)語句換成我們自己的,跳轉(zhuǎn)到包含webView的界面就大功告成了。
????最后的方案雖然很簡單,但是網(wǎng)上的解答都不盡如人意。所以獻丑記下解決的過程,希望能幫助到有需要的人~