How to listen for a WebView finishing loading a URL?

前端 未结 17 698
予麋鹿
予麋鹿 2020-11-22 05:40

I have a WebView that is loading a page from the Internet. I want to show a ProgressBar until the loading is complete.

How do I listen for

相关标签:
17条回答
  • 2020-11-22 06:06

    Just to show progress bar, "onPageStarted" and "onPageFinished" methods are enough; but if you want to have an "is_loading" flag (along with page redirects, ...), this methods may executed with non-sequencing, like "onPageStarted > onPageStarted > onPageFinished > onPageFinished" queue.

    But with my short test (test it yourself.), "onProgressChanged" method values queue is "0-100 > 0-100 > 0-100 > ..."

    private boolean is_loading = false;
    
    webView.setWebChromeClient(new MyWebChromeClient(context));
    
    private final class MyWebChromeClient extends WebChromeClient{
        @Override
        public void onProgressChanged(WebView view, int newProgress) {
            if (newProgress == 0){
                is_loading = true;
            } else if (newProgress == 100){
                is_loading = false;
            }
            super.onProgressChanged(view, newProgress);
        }
    }
    

    Also set "is_loading = false" on activity close, if it is a static variable because activity can be finished before page finish.

    0 讨论(0)
  • 2020-11-22 06:07

    thanks for the answers. It helped me, but I had to improve it a bit for my needs. I had several pagestarts and finishes so I added a timer which checks if atfer the pagefinish is started a new pagestart. Okay, bad explanation. See the code :)

    myWebView.setWebViewClient(new WebViewClient() {
            boolean loadingFinished = true;
            boolean redirect = false;
    
            long last_page_start;
            long now;
    
            // Load the url
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                if (!loadingFinished) {
                    redirect = true;
                }
    
                loadingFinished = false;
                view.loadUrl(url);
                return false;
            }
    
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                Log.i("p","pagestart");
                loadingFinished = false;
                last_page_start = System.nanoTime();
                show_splash();
            }
    
            // When finish loading page
            public void onPageFinished(WebView view, String url) {
                Log.i("p","pagefinish");
                if(!redirect){
                    loadingFinished = true;
                }
                //call remove_splash in 500 miSec
                if(loadingFinished && !redirect){
                    now = System.nanoTime();
                    new android.os.Handler().postDelayed(
                            new Runnable() {
                                public void run() {
                                    remove_splash();
                                }
                            },
                            500);
                } else{
                    redirect = false;
                }
            }
            private void show_splash() {
                if(myWebView.getVisibility() == View.VISIBLE) {
                    myWebView.setVisibility(View.GONE);
                    myWebView_splash.setVisibility(View.VISIBLE);
                }
            }
            //if a new "page start" was fired dont remove splash screen
            private void remove_splash() {
                if (last_page_start < now) {
                    myWebView.setVisibility(View.VISIBLE);
                    myWebView_splash.setVisibility(View.GONE);
                }
            }
    
    });
    
    0 讨论(0)
  • 2020-11-22 06:08

    I found one elegant solution as well, have not tested it rigorously though:

    public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                if (m_webView.getProgress() == 100) {
                    progressBar.setVisibility(View.GONE);
                    m_webView.setVisibility(View.VISIBLE);
                }
            } 
    
    0 讨论(0)
  • 2020-11-22 06:09

    Here's a method which allows you to register a Runnable to be executed once a particular web address has finished loading. We associate each Runnable with a corresponding URL String in a Map, and we use the WebView's getOriginalUrl() method to choose the appropriate callback.

    package io.github.cawfree.webviewcallback;
    
    /**
     *  Created by Alex Thomas (@Cawfree), 30/03/2017.
     **/
    
    import android.net.http.SslError;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.webkit.SslErrorHandler;
    import android.webkit.WebView;
    import android.webkit.WebViewClient;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /** An Activity demonstrating how to introduce a callback mechanism into Android's WebView. */
    public class MainActivity extends AppCompatActivity {
    
        /* Member Variables. */
        private WebView               mWebView;
        private Map<String, Runnable> mCallbackMap;
    
        /** Create the Activity. */
        @Override protected final void onCreate(final Bundle pSavedInstanceState) {
            // Initialize the parent definition.
            super.onCreate(pSavedInstanceState);
            // Set the Content View.
            this.setContentView(R.layout.activity_main);
            // Fetch the WebView.
            this.mWebView     = (WebView)this.findViewById(R.id.webView);
            this.mCallbackMap = new HashMap<>();
            // Define the custom WebClient. (Here I'm just suppressing security errors, since older Android devices struggle with TLS.)
            this.getWebView().setWebViewClient(new WebViewClient() {
                /** Handle when a request has been launched. */
                @Override public final void onPageFinished(final WebView pWebView, final String pUrl) {
                    // Determine whether we're allowed to process the Runnable; if the page hadn't been redirected, or if we've finished redirection.
                    if(pUrl.equals(pWebView.getOriginalUrl())) {
                        // Fetch the Runnable for the OriginalUrl.
                        final Runnable lRunnable = getCallbackMap().get(pWebView.getOriginalUrl());
                        // Is it valid?
                        if(lRunnable != null) { lRunnable.run(); }
                    }
                    // Handle as usual.
                    super.onPageFinished(pWebView, pUrl);
                }
                /** Ensure we handle SSL state properly. */
                @Override public final void onReceivedSslError(final WebView pWebView, final SslErrorHandler pSslErrorHandler, final SslError pSslError) { pSslErrorHandler.proceed(); }
            });
            // Assert that we wish to visit Zonal's website.
            this.getWebView().loadUrl("http://www.zonal.co.uk/");
            // Align a Callback for Zonal; this will be serviced once the page has loaded.
            this.getCallbackMap().put("http://www.zonal.co.uk/", new Runnable() {     @Override public void run() { /* Do something. */ } });
        }
    
        /* Getters. */
        public final WebView getWebView() {
            return this.mWebView;
        }
    
        private final Map<String, Runnable> getCallbackMap() {
            return this.mCallbackMap;
        }
    
    }
    
    0 讨论(0)
  • 2020-11-22 06:11

    I have simplified NeTeInStEiN's code to be like this:

    mWebView.setWebViewClient(new WebViewClient() {
            private int       webViewPreviousState;
            private final int PAGE_STARTED    = 0x1;
            private final int PAGE_REDIRECTED = 0x2;
    
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String urlNewString) {
                webViewPreviousState = PAGE_REDIRECTED;
                mWebView.loadUrl(urlNewString);
                return true;
            }
    
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
                webViewPreviousState = PAGE_STARTED;
                if (dialog == null || !dialog.isShowing())
                    dialog = ProgressDialog.show(WebViewActivity.this, "", getString(R.string.loadingMessege), true, true,
                            new OnCancelListener() {
    
                                @Override
                                public void onCancel(DialogInterface dialog) {
                                    // do something
                                }
                            });
            }
    
            @Override
            public void onPageFinished(WebView view, String url) {
    
                if (webViewPreviousState == PAGE_STARTED) {
                    dialog.dismiss();
                    dialog = null;
                }
    
            }
     });
    

    It is easy to understand, OnPageFinished if the previous callback is on onPageStarted, so the page is completely loaded.

    0 讨论(0)
  • 2020-11-22 06:11

    Use setWebViewClient() and override onPageFinished()

    0 讨论(0)
提交回复
热议问题