487

WebViewインターネットからページをロードしている があります。ProgressBar読み込みが完了するまで表示したい。

のページ読み込みの完了をリッスンするにはどうすればよいWebViewですか?

4

18 に答える 18

768

WebViewClientを拡張し、次のようにonPageFinished()を呼び出します。

mWebView.setWebViewClient(new WebViewClient() {

   public void onPageFinished(WebView view, String url) {
        // do your stuff here
    }
});
于 2010-06-30T12:34:01.567 に答える
161

@ianこれは100%正確ではありません。ページに複数の iframe がある場合、複数の onPageFinished (および onPageStarted) があります。また、複数のリダイレクトがある場合も失敗する可能性があります。このアプローチは、(ほぼ) すべての問題を解決します。

boolean loadingFinished = true;
boolean redirect = false;

mWebView.setWebViewClient(new WebViewClient() {

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String urlNewString) {
        if (!loadingFinished) {
            redirect = true;
        }

        loadingFinished = false;
        webView.loadUrl(urlNewString);
        return true;
    }

    @Override
    public void onPageStarted(WebView view, String url) {
        loadingFinished = false;
        //SHOW LOADING IF IT ISNT ALREADY VISIBLE  
    }

    @Override
    public void onPageFinished(WebView view, String url) {
        if (!redirect) {
           loadingFinished = true;
            //HIDE LOADING IT HAS FINISHED
        } else {
            redirect = false; 
        }
    }
});

アップデート:

ドキュメントによると、 onPageStarted は、埋め込みフレームのコンテンツが変更されたとき、つまりターゲットが iframe であるリンクをクリックしたときに呼び出されません。

Twitter で、pageFinished のみが呼び出され、ロジックが少し混乱しているような特定のケースを見つけました。それを解決するために、X秒後にロードを削除するスケジュールされたタスクを追加しました。これは、他のすべての場合には必要ありません。

更新 2 :

現在の Android WebView 実装では:

boolean loadingFinished = true;
boolean redirect = false;

    mWebView.setWebViewClient(new WebViewClient() {

        @Override
        public boolean shouldOverrideUrlLoading(
                WebView view, WebResourceRequest request) {
            if (!loadingFinished) {
               redirect = true;
            }

            loadingFinished = false;
            webView.loadUrl(request.getUrl().toString());
            return true;
        }

        @Override
        public void onPageStarted(
                WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            loadingFinished = false;
            //SHOW LOADING IF IT ISNT ALREADY VISIBLE  
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            if (!redirect) {
               loadingFinished = true;
                //HIDE LOADING IT HAS FINISHED
            } else {
                redirect = false; 
            }
        }
    });
于 2011-03-02T20:21:38.017 に答える
41

私は@NeTeInStEiN(および@polen)ソリューションにかなり偏っていますが、複数のブール値または状態ウォッチャーの代わりにカウンターを使用して実装していました(別のフレーバーですが、共有できると思いました)。JSのニュアンスがありますが、ロジックは少し理解しやすいと思います。

private void setupWebViewClient() {
    webView.setWebViewClient(new WebViewClient() {
        private int running = 0; // Could be public if you want a timer to check.

        @Override
        public boolean shouldOverrideUrlLoading(WebView webView, String urlNewString) {
            running++;
            webView.loadUrl(urlNewString);
            return true;
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            running = Math.max(running, 1); // First request move it to 1.
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            if(--running == 0) { // just "running--;" if you add a timer.
                // TODO: finished... if you want to fire a method.
            }
        }
    });
}
于 2013-07-23T16:23:54.053 に答える
33

私も1つのエレガントなソリューションを見つけましたが、厳密にはテストしていません:

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);
            }
        } 
于 2015-10-13T08:01:16.763 に答える
24

進行状況バーを表示したい場合は、ページの完了だけでなく、進行状況の変更イベントをリッスンする必要があります。

mWebView.setWebChromeClient(new WebChromeClient(){

            @Override
            public void onProgressChanged(WebView view, int newProgress) {

                //change your progress bar
            }


        });

ところで、メソッド onPageFinished をオーバーライドする Indeterminate ProgressBar だけを表示したい場合は十分です

于 2010-06-30T13:55:48.003 に答える
23

NeTeInStEiNのコードを次のように単純化しました。

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;
            }

        }
 });

前のコールバックが onPageStarted にある場合は、OnPageFinished というのがわかりやすいので、ページは完全に読み込まれます。

于 2011-08-05T05:04:34.270 に答える
6

setWebViewClient()を使用し、 onPageFinished ()をオーバーライドします

于 2010-06-30T12:33:21.007 に答える
5

進行状況は、 webviewクラスのgetProgressメソッドで追跡できます。

進捗状況を初期化する

private int mProgressStatus = 0;

次に、次のようにロードするための AsyncTask :

private class Task_News_ArticleView extends AsyncTask<Void, Void, Void> {
    private final ProgressDialog dialog = new ProgressDialog(
            your_class.this);

    // can use UI thread here
    protected void onPreExecute() {
        this.dialog.setMessage("Loading...");
        this.dialog.setCancelable(false);
        this.dialog.show();
    }

    @Override
    protected Void doInBackground(Void... params) {
        try {
            while (mProgressStatus < 100) {
                mProgressStatus = webview.getProgress();

            }
        } catch (Exception e) {

        }
        return null;

    }

    protected void onPostExecute(Void result) {
        if (this.dialog.isShowing()) {
            this.dialog.dismiss();
        }
    }
}
于 2010-06-30T12:48:22.877 に答える
5

答えてくれてありがとう。それは私を助けましたが、私のニーズに合わせて少し改善する必要がありました. いくつかのページ開始と終了があったため、ページ終了が新しいページ開始で開始されたかどうかを確認するタイマーを追加しました。さて、悪い説明。コードを参照してください:)

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);
            }
        }

});
于 2015-05-19T12:23:26.547 に答える
4

Kotlin ユーザー向け:

webView.webViewClient = object : WebViewClient() {
            override fun onPageFinished(view: WebView?, url: String?) {
                // do your logic
            }
        }

ただし、オーバーライドできるメソッドはたくさんあります

于 2019-05-28T12:47:14.587 に答える
0

Runnable特定の Web アドレスの読み込みが完了したときに実行されるを登録できるメソッドを次に示します。それぞれRunnableを 内の対応する URLStringに関連付け、のメソッドMapを使用して適切なコールバックを選択します。WebViewgetOriginalUrl()

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;
    }

}
于 2017-03-30T15:14:13.617 に答える
0

これを使用してください。`var currentUrl = "google.com" var partOfUrl = currentUrl.substring(0, currentUrl.length-2)

webView.setWebViewClient(オブジェクト: WebViewClient() {

override fun onLoadResource(WebView view, String url) {
     //call loadUrl() method  here 
     // also check if url contains partOfUrl, if not load it differently.
     if(url.contains(partOfUrl, true)) {
         //it should work if you reach inside this if scope.
     } else if(!(currentUrl.startWith("w", true))) {
         webView.loadurl("www.$currentUrl")

     } else if(!(currentUrl.startWith("h", true))) {
         webView.loadurl("https://$currentUrl")

     } else { ...}


 }

override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler?, error: SslError?) {
   // you can call again loadUrl from here too if there is any error.
}

//また、onReceiveError などのエラー用の他のオーバーライド メソッドをオーバーライドして、これらすべてのメソッドが次々とどのように呼び出されるか、およびブレーク ポイントを使用してデバッグ中にどのように動作するかを確認する必要があります。} `

于 2020-03-31T05:01:15.580 に答える