Android用內(nèi)置WebView打開TextView文本中的超鏈接

????下午產(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);
    }
}

????說下幾個改動(代碼中注釋的兩行):

  1. 由于頁面跳轉(zhuǎn)我們需要用到原頁面的上下文,于是修改了構(gòu)造函數(shù),加入了Context;
  2. URLSpan是ClickableSpan的子類,實現(xiàn)了getURL()的方法,所以這里要換成它我們才能取到鏈接地址,link[0]就是我們點擊到的超鏈接字符串,通過link[0].getURL()我們可以獲得它的鏈接地址傳給下個頁面;
  3. 有了上下文context和鏈接地址url,我們就可以把原來的跳轉(zhuǎn)語句換成我們自己的,跳轉(zhuǎn)到包含webView的界面就大功告成了。

????最后的方案雖然很簡單,但是網(wǎng)上的解答都不盡如人意。所以獻丑記下解決的過程,希望能幫助到有需要的人~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容