在WebView中打开网址,而不是默认的浏览器 [英] Open URL in WebView instead of default Browser

查看:250
本文介绍了在WebView中打开网址,而不是默认的浏览器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在的TextView 创建了一些链接简单的网​​页视图应用程序,并在网页流量而不是默认的浏览器。我的的TextView 包含各种不同的URL,我想在我的应用程序的WebView打开每个环节。

I am creating simple Webview application with some links on textview and open those links in webview instead of default browser. My textview contains various different URLS and i am trying to open each link in webview of my app.

下面code:

tv.setText("www.google.com  www.facebook.com  www.yahoo.com");
tv.setMovementMethod(LinkMovementMethod.getInstance());;
tv.setText(Html.fromHtml(tv.getText().toString()));
Linkify.addLinks(tv, Linkify.WEB_URLS);


WebViewClient yourWebClient = new WebViewClient()
       {
           // Override page so it's load on my view only
           @Override
           public boolean shouldOverrideUrlLoading(WebView  view, String  url)
           {
            // This line we let me load only pages inside Firstdroid Webpage
            if ( url.contains("www") == true )
               // Load new URL Don't override URL Link
               return false;

            // Return true to override url loading (In this case do nothing).
            return true;
           }
       };

wv.getSettings().setJavaScriptEnabled(true);   
    wv.getSettings().setSupportZoom(true);      

    wv.getSettings().setBuiltInZoomControls(true); 
    wv.setWebViewClient(yourWebClient);

    // Load URL
    wv.loadUrl(url);

已经与<一试href=\"http://stackoverflow.com/questions/7255249/how-can-we-open-textviews-links-into-webview\">this, <一href=\"http://stackoverflow.com/questions/1697084/handle-textview-link-click-in-my-android-app\">this和<一个href=\"http://stackoverflow.com/questions/6636283/open-a-link-in-a-webview-instead-of-default-browser\">this例子,但未能解决在的TextView 多个链接我的问题。请帮我解决这个问题。感谢您的帮助。

Already tried with this, this and this examples but couldn't solve my issue with multiple links in the textview. Please help me to solve this problem. Thanks for your help.

修改
我的的TextView 包含字符串,如:

hello xyz some more statements... xyz.com/abc/
hello xyz some more statements... xyz.com/abc/
hello xyz some more statements... xyz.com/abc/
hello xyz some more statements... xyz.com/abc/

喜欢这个?有许多字符串和多个URL的

Like this it has many strings and multiple URL's

推荐答案

需要解决以下几个问题:

The following problems need to be solved:


  1. Linkify TextView的

  2. 找到一种方式来收听TextView的
  3. 一个链接的点击
  4. 获取点击的链接的URL,并在WebView中加载它

  5. 可选:使TextView的点击,而不会丢失的能力来选择文本

  6. 可选:处理TextView的格式文本(不同的文字大小和样式)

  1. Linkify the TextView
  2. Find a way to listen to a click on a link in the TextView
  3. Get the url of the clicked link and load it in the WebView
  4. Optional: make the TextView clickable without losing the ability to select text
  5. Optional: handle formatted text in the TextView (different text sizes and styles)

#1 Linkify TextView的

这是最简单的问题,你已经解决了的那一个。我建议做这种方式:

That's the easiest problem and you already solved that one. I suggest to do it this way:

String text = "These are some sample links:\nwww.google.com\nwww.facebook.com\nwww.yahoo.com";
Spannable spannable = new SpannableString( Html.fromHtml(text) );
Linkify.addLinks(spannable, Linkify.WEB_URLS);

我使用的是这里Spannable解决问题#2。

I'm using a Spannable here to solve problem #2.

#2#+ 3听上链接的点击,并在web视图

要找出点击一个链接时,并检索我们要打开,我们通过我们的LinkSpan替换的TextView所有URLSpans的URL(这就是为什么我们需要一个Spannable):

To find out when a link is clicked and retrieve the URL we have to open, we replace all URLSpans in the TextView by our LinkSpan (that's why we need a Spannable):

URLSpan[] spans = spannable.getSpans(0, spannable.length(), URLSpan.class);
for (URLSpan urlSpan : spans) {
    LinkSpan linkSpan = new LinkSpan(urlSpan.getURL());
    int spanStart = spannable.getSpanStart(urlSpan);
    int spanEnd = spannable.getSpanEnd(urlSpan);
    spannable.setSpan(linkSpan, spanStart, spanEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    spannable.removeSpan(urlSpan);
}

我们的LinkSpan根本抓起点击链接并打开它在web视图:

Our LinkSpan simply grabs the clicked url and opens it in the WebView:

private class LinkSpan extends URLSpan {
    private LinkSpan(String url) {
        super(url);
    }

    @Override
    public void onClick(View view) {
        String url = getURL();
        if (mWebView != null && url != null) {
            mWebView.loadUrl(url);
        }
    }
}

现在很明显,我们必须保持对的WebView的引用在一个实例变量,使这项工作。为了使这个答案尽可能短,我选择了定义LinkSpan作为一个内部类,但我建议将其定义为顶级。注册一个监听器或通过web视图作为参数的构造来代替。

Now obviously we have to keep a reference to the WebView in an instance variable to make this work. To make this answer as short as possible I chose to define LinkSpan as an inner class but I'd recommend to define it as a top-level. Register a listener or pass the WebView as a parameter to the constructor instead.

如果没有设置MovementMethod到LinkMovementMethod TextView的不会打开链接都:

Without setting the MovementMethod to LinkMovementMethod the TextView won't open links at all:

tv.setMovementMethod(LinkMovementMethod.getInstance());
tv.setText(spannable, BufferType.SPANNABLE);

最后但并非最不重要,让我们确保的WebView不会启动浏览器,但在应用程序中加载网页:

Last but not least let's make sure the WebView doesn't start the browser but loads the page within the app:

mWebView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        // we handle the url ourselves if it's a network url (http / https) 
        return ! URLUtil.isNetworkUrl(url);
    }
});

#4可点击和可选择的TextView + 5#格式化文本

如果该MovementMethod设置为LinkMovementMethod您可以单击链接,但你不能选择文本的话(你需要ArrowKeyMovementMethod为该)。为了解决这个问题,我创建从ArrowKeyMovementMethod继承,并增加了用户点击链接能力的定制MovementMethod类。最重要的是它能够处理格式的文本。所以如果你决定在TextView中使用不同的字体大小和样式以下MovementMethod将其覆盖(与EditTexts工程,以及):

If the MovementMethod is set to LinkMovementMethod you can click links but you can't select text any more (you need ArrowKeyMovementMethod for that). To solve this I created an custom MovementMethod class that inherits from ArrowKeyMovementMethod and adds the ability to click links. On top of that it is able to deal with formatted text. So if you decide to use different font sizes and styles in the TextView the following MovementMethod will have it covered (works with EditTexts as well):

/**
 * ArrowKeyMovementMethod does support selection of text but not the clicking of links.
 * LinkMovementMethod does support clicking of links but not the selection of text.
 * This class adds the link clicking to the ArrowKeyMovementMethod.
 * We basically take the LinkMovementMethod onTouchEvent code and remove the line
 *      Selection.removeSelection(buffer);
 * which deselects all text when no link was found.
 */
public class EnhancedLinkMovementMethod extends ArrowKeyMovementMethod {

    private static EnhancedLinkMovementMethod sInstance;

    private static Rect sLineBounds = new Rect();

    public static MovementMethod getInstance() {
        if (sInstance == null) {
            sInstance = new EnhancedLinkMovementMethod();
        }
        return sInstance;
    }

    @Override
    public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
        int action = event.getAction();

        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {

            int index = getCharIndexAt(widget, event);
            if (index != -1) {
                ClickableSpan[] link = buffer.getSpans(index, index, 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);
    }

    private int getCharIndexAt(TextView textView, MotionEvent event) {
        // get coordinates
        int x = (int) event.getX();
        int y = (int) event.getY();
        x -= textView.getTotalPaddingLeft();
        y -= textView.getTotalPaddingTop();
        x += textView.getScrollX();
        y += textView.getScrollY();

        /*
         * Fail-fast check of the line bound.
         * If we're not within the line bound no character was touched
         */
        Layout layout = textView.getLayout();
        int line = layout.getLineForVertical(y);
        synchronized (sLineBounds) {
            layout.getLineBounds(line, sLineBounds);
            if (! sLineBounds.contains(x, y)) {
                return -1;
            }
        }

        // retrieve line text
        Spanned text = (Spanned) textView.getText();
        int lineStart = layout.getLineStart(line);
        int lineEnd = layout.getLineEnd(line);
        int lineLength = lineEnd - lineStart;
        if (lineLength == 0) {
            return -1;
        }
        Spanned lineText = (Spanned) text.subSequence(lineStart, lineEnd);

        // compute leading margin and subtract it from the x coordinate
        int margin = 0;
        LeadingMarginSpan[] marginSpans = lineText.getSpans(0, lineLength, LeadingMarginSpan.class);
        if (marginSpans != null) {
            for (LeadingMarginSpan span : marginSpans) {
                margin += span.getLeadingMargin(true);
            }
        }
        x -= margin;

        // retrieve text widths
        float[] widths = new float[lineLength];
        TextPaint paint = textView.getPaint();
        paint.getTextWidths(lineText, 0, lineLength, widths);

        // scale text widths by relative font size (absolute size / default size)
        final float defaultSize = textView.getTextSize();
        float scaleFactor = 1f;
        AbsoluteSizeSpan[] absSpans = lineText.getSpans(0, lineLength, AbsoluteSizeSpan.class);
        if (absSpans != null) {
            for (AbsoluteSizeSpan span : absSpans) {
                int spanStart = lineText.getSpanStart(span);
                int spanEnd = lineText.getSpanEnd(span);
                scaleFactor = span.getSize() / defaultSize;
                int start = Math.max(lineStart, spanStart);
                int end = Math.min(lineEnd, spanEnd);
                for (int i = start; i < end; i++) {
                    widths[i] *= scaleFactor;
                }
            }
        }

        // find index of touched character
        float startChar = 0;
        float endChar = 0;
        for (int i = 0; i < lineLength; i++) {
            startChar = endChar;
            endChar += widths[i];
            if (endChar >= x) {
                // which "end" is closer to x, the start or the end of the character?
                int index = lineStart + (x - startChar < endChar - x ? i : i + 1);
                //Logger.e(Logger.LOG_TAG, "Found character: " + (text.length()>index ? text.charAt(index) : ""));
                return index;
            }
        }

        return -1;
    }
}

完成活动code

下面是完整的示例活动code,我用。它应该做的正是你想要的。它是用我的EnhandedMovementMethod但你可以用一个简单的LinkMovementMethod(与缺点前面提到的)。

Here's the complete sample Activity code that I used. It should do exactly what you want. It's using my EnhandedMovementMethod but you can use a simple LinkMovementMethod (with the drawbacks mentioned before).

public class LinkTestActivity extends Activity {

    private WebView mWebView;

    @SuppressLint("SetJavaScriptEnabled")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        mWebView = (WebView) findViewById(R.id.webView);
        TextView tv = (TextView) findViewById(R.id.textView);

        String text = "These are some sample links:\nwww.google.com\nwww.facebook.com\nwww.yahoo.com";

        // Linkify the TextView
        Spannable spannable = new SpannableString( Html.fromHtml(text) );
        Linkify.addLinks(spannable, Linkify.WEB_URLS);

        // Replace each URLSpan by a LinkSpan
        URLSpan[] spans = spannable.getSpans(0, spannable.length(), URLSpan.class);
        for (URLSpan urlSpan : spans) {
            LinkSpan linkSpan = new LinkSpan(urlSpan.getURL());
            int spanStart = spannable.getSpanStart(urlSpan);
            int spanEnd = spannable.getSpanEnd(urlSpan);
            spannable.setSpan(linkSpan, spanStart, spanEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            spannable.removeSpan(urlSpan);
        }

        // Make sure the TextView supports clicking on Links
        tv.setMovementMethod(EnhancedLinkMovementMethod.getInstance());
        tv.setText(spannable, BufferType.SPANNABLE);

        // Make sure we handle clicked links ourselves
        mWebView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                // we handle the url ourselves if it's a network url (http / https) 
                return ! URLUtil.isNetworkUrl(url);
            }
        });

        mWebView.getSettings().setJavaScriptEnabled(true);   
        mWebView.getSettings().setSupportZoom(true);      
        mWebView.getSettings().setBuiltInZoomControls(true);
    }

    private class LinkSpan extends URLSpan {
        private LinkSpan(String url) {
            super(url);
        }

        @Override
        public void onClick(View view) {
            String url = getURL();
            if (mWebView != null && url != null) {
                mWebView.loadUrl(url);
            }
        }
    }
}

这篇关于在WebView中打开网址,而不是默认的浏览器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆