Comment écouter une WebView finissant de charger une URL?

447

J'ai un WebViewqui charge une page à partir d'Internet. Je veux afficher un ProgressBarjusqu'à ce que le chargement soit terminé.

Comment écouter la fin du chargement de la page d'un WebView?

Janusz
la source
1
Veuillez considérer que ma réponse est correcte, car elle résout certains problèmes que ne pose pas ian.
neteinstein
Je pense qu'une meilleure façon d'appeler le code Java natif avec js lors du chargement de la page. Référez-vous à cette réponse, bien que ce soit pour iOS, mais l'idée s'applique ici aussi .
Kris Roofe
Consultez ma réponse ci-dessous pour une solution minimale et concise
Skynet

Réponses:

716

Étendre WebViewClient et appelez onPageFinished () comme suit:

mWebView.setWebViewClient(new WebViewClient() {

   public void onPageFinished(WebView view, String url) {
        // do your stuff here
    }
});
ian
la source
J'ai des problèmes avec les chargements externes lorsque Internet n'est pas si rapide. Par exemple Google Analytics ou d'autres trucs comme ça. J'ai essayé quelques solutions de contournement et cela s'est beaucoup amélioré, mais pas encore parfait. Parfois, l'application se fige sur l'écran de chargement et il est impossible de quitter, à moins que vous ne déconnectiez le réseau ou que vous vous connectiez à un autre bon réseau. Je ne sais pas encore comment résoudre ce problème, j'essaie.
Felipe
1
Fonctionne parfaitement. Vous pouvez utiliser mWebView.setVisibility (View.INVISIBLE) avant le chargement. Une fois le chargement terminé, remettez-le sur View.VISIBLE. Je l'ai utilisé avec cet écran de démarrage: android-developers.blogspot.de/2009/03/…
Johan Hoeksma
39
Ce n'est pas du tout une solution. Il n'y a aucune garantie que la page est déjà chargée lorsque cette méthode est appelée.
Hawk
3
C'est une mauvaise conception de la part de Google. Presque tout le temps, lorsque cette action se termine, vous voulez faire quelque chose orienté autour de l'activité parent, pas la vue Web elle-même. Remplacer une fonction au lieu de souscrire à un événement est un anti-modèle courant et je n'aime pas le développement Android.
Ryan
6
Cette méthode ne garantit pas la fin du chargement et peut être appelée plusieurs fois si le chargement de l'URL nécessite une navigation intermédiaire. Donc, cela est appelé plusieurs fois. Cependant, c'est un moyen de le vérifier.
débutant le
150

@ian ce n'est pas précis à 100%. Si vous avez plusieurs iframes dans une page, vous aurez plusieurs onPageFinished (et onPageStarted). Et si vous avez plusieurs redirections, cela peut également échouer. Cette approche résout (presque) tous les problèmes:

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

MISE À JOUR:

Selon la documentation: onPageStarted ne sera PAS appelé lorsque le contenu d'un cadre intégré change, c'est-à-dire en cliquant sur un lien dont la cible est un iframe.

J'ai trouvé un cas spécifique comme celui-ci sur Twitter où seule une pageFinished a été appelée et a un peu perturbé la logique. Pour résoudre ce problème, j'ai ajouté une tâche planifiée pour supprimer le chargement après X secondes. Ce n'est pas nécessaire dans tous les autres cas.

MISE À JOUR 2 :

Maintenant avec l'implémentation actuelle d'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; 
            }
        }
    });
neteinstein
la source
3
Vous avez probablement remarqué la mise en garde dans le document de onPageStarted: onPageStarted ne sera PAS appelé lorsque le contenu d'un cadre intégré change, c'est-à-dire en cliquant sur un lien dont la cible est un iframe. Cela peut donc fausser la logique dans ces cas. BTW, la simplification de @ polen fonctionne-t-elle vraiment?
an00b
1
Belle prise, jamais remarqué le truc du cadre. Je n'ai pas essayé le code du polen .. le seul que je peux assurer que le travail est celui ci-dessus que j'utilise.
neteinstein
3
Juste une correction mineure. C'est en fait "public void onPageStarted (vue WebView, URL de chaîne, favicon Bitmap)" au lieu de "public void onPageStarted (vue WebView, chaîne url)"
MrMaffen
Ne fonctionne pas pour certains des sites les plus récents qui ne finissent jamais de charger ... par exemple, "agoda.com". Vous ne recevez jamais l'appel onPageFinished car il s'agit d'une redirection.
kenyee
J'ai vu onPageFinished être appelé deux fois lors d'une redirection. Mais, ce que vous avez dit "Si vous avez plusieurs iframes dans une page, vous aurez plusieurs onPageFinished (et onPageStarted)" n'est pas correct selon la documentation de onPageFinished: "Cette méthode n'est appelée que pour le cadre principal."
grenat
40

Je suis assez partisan de la solution @NeTeInStEiN (et @polen) mais je l'aurais implémentée avec un compteur au lieu de plusieurs booléens ou observateurs d'état (juste une autre saveur mais je pensais qu'elle pourrait partager). Il a une nuance JS à ce sujet, mais je pense que la logique est un peu plus facile à comprendre.

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.
            }
        }
    });
}
SciSpear
la source
2
Votre code semble bon. J'ai essayé la même chose pour ma vue Web qui se charge des données html et non des URL. Mais celui-ci déclenche onPageFinished si la première vue Web se charge rapidement et avant que la seconde ne commence à se charger. Scénario normal. running = 1, running = 2, --running = 1, --running = 0. Scénario inhabituel qui échoue - exécution = 1, - exécution = 0, exécution = 1 exécution = 0
Ajith Memana
1
Il existe également un autre scénario, lorsqu'un événement n'est pas déclenché pour une raison quelconque, la partie TODO ne sera jamais atteinte. Vous avez donc besoin d'une minuterie pour vérifier les délais. Ou vous pouvez appeler une fonction java exportée en javascript lorsque vous savez que tout est correctement chargé. Quelque chose comme documentReady () ou quelque chose comme ça.
Codebeat
pourquoi pas juste running = 1;dedans onPageStarted()?
Choletski
@Choletski Parce que le maximum de 1 et un nombre supérieur à 1 n'est pas 1.
Matthew Read
25

J'ai également trouvé une solution élégante, mais je ne l'ai pas testée rigoureusement:

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);
            }
        } 
Skynet
la source
2
Je l'ai testé et cela fonctionne parfaitement, vous pouvez bien sûr l'appeler de l'extérieur de la méthode onPageFinished et utiliser un gestionnaire pour vérifier à intervalles courts - dans les cas, vous ne voulez pas étendre la classe WebViewClient.
Gal Rom
1
Je crois que cela pourrait être mieux que la réponse acceptée, il vous suffirait de vérifier la onError et vous êtes prêt.
Evin1_
1
Ce devrait être la réponse acceptée.
زياد
1
Vote positif pour celui-ci
Khdkls
23

J'ai simplifié le code de NeTeInStEiN pour qu'il ressemble à ceci:

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

        }
 });

Il est facile de comprendre, OnPageFinished si le rappel précédent est sur onPageStarted, de sorte que la page est complètement chargée.

polen
la source
3
@polen PAGE_STARTED n'est jamais effacé? Que faire si shouldOverrideUrlLoading () n'est jamais appelé?
an00b
20

Si vous voulez afficher une barre de progression, vous devez écouter un événement de changement de progression, pas seulement pour l'achèvement de la page:

mWebView.setWebChromeClient(new WebChromeClient(){

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

                //change your progress bar
            }


        });

BTW si vous voulez afficher juste un ProgressBar indéterminé remplaçant la méthode onPageFinished est suffisant

Francesco Laurita
la source
5

Vous pouvez suivre le progrès Staus par la getProgress méthode dans WebView classe.

Initialiser l'état d'avancement

private int mProgressStatus = 0;

puis l'AsyncTask pour le chargement comme ceci:

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();
        }
    }
}
Praveen
la source
mProgressStatus = webview.getProgress (); doit être appelé à partir d'un thread d'interface utilisateur.
Skynet
5

merci pour les réponses. Cela m'a aidé, mais j'ai dû l'améliorer un peu pour mes besoins. J'ai eu plusieurs pagestarts et finitions donc j'ai ajouté une minuterie qui vérifie si après la pagefinish est démarré un nouveau pagestart. D'accord, mauvaise explication. Voir le 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);
            }
        }

});
EscapeNetscape
la source
2

Voici une nouvelle méthode pour détecter le chargement d'une URL en utilisant la capacité d'Android pour les hooks JavaScript . En utilisant ce modèle, nous exploitons la connaissance de JavaScript de l'état du document pour générer un appel de méthode native dans le runtime Android. Ces appels accessibles en JavaScript peuvent être effectués à l'aide de l' @JavaScriptInterfaceannotation.

Cette implémentation nécessite que nous appelions setJavaScriptEnabled(true)les WebViewparamètres de, de sorte qu'elle pourrait ne pas convenir en fonction des exigences de votre application, par exemple des problèmes de sécurité.

src / io / github / cawfree / webviewcallback / MainActivity.java (Jelly Bean, API niveau 16)

package io.github.cawfree.webviewcallback;

/**
 *  Created by Alex Thomas (@Cawfree), 30/03/2017.
 **/

import android.net.http.SslError;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.JavascriptInterface;
import android.webkit.SslErrorHandler;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

/** An Activity demonstrating how to introduce a callback mechanism into Android's WebView. */
public class MainActivity extends AppCompatActivity {

    /* Static Declarations. */
    private static final String HOOK_JS             = "Android";
    private static final String URL_TEST            = "http://www.zonal.co.uk/";
    private static final String URL_PREPARE_WEBVIEW = "";

    /* Member Variables. */
    private WebView mWebView = null;

    /** 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);
        // Enable JavaScript.
        this.getWebView().getSettings().setJavaScriptEnabled(true);
        // Define the custom WebClient. (Here I'm just suppressing security errors, since older Android devices struggle with TLS.)
        this.getWebView().setWebViewClient(new WebViewClient() { @Override     public final void onReceivedSslError(final WebView pWebView, final SslErrorHandler pSslErrorHandler, final SslError pSslError) { pSslErrorHandler.proceed(); } });
        // Define the WebView JavaScript hook.
        this.getWebView().addJavascriptInterface(this, MainActivity.HOOK_JS);
        // Make this initial call to prepare JavaScript execution.
        this.getWebView().loadUrl(MainActivity.URL_PREPARE_WEBVIEW);
    }

    /** When the Activity is Resumed. */
    @Override protected final void onPostResume() {
        // Handle as usual.
        super.onPostResume();
        // Load the URL as usual.
        this.getWebView().loadUrl(MainActivity.URL_TEST);
        // Use JavaScript to embed a hook to Android's MainActivity. (The onExportPageLoaded() function implements the callback, whilst we add some tests for the state of the WebPage so as to infer when to export the event.)
        this.getWebView().loadUrl("javascript:" + "function onExportPageLoaded() { " + MainActivity.HOOK_JS + ".onPageLoaded(); }" + "if(document.readyState === 'complete') { onExportPageLoaded(); } else { window.addEventListener('onload', function () { onExportPageLoaded(); }, false); }");
    }

    /** Javascript-accessible callback for declaring when a page has loaded. */
    @JavascriptInterface @SuppressWarnings("unused") public final void onPageLoaded() {
        // Display the Message.
        Toast.makeText(this, "Page has loaded!", Toast.LENGTH_SHORT).show();
    }

    /* Getters. */
    public final WebView getWebView() {
        return this.mWebView;
    }

}

res / layout / activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<WebView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/webView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
/>

Essentiellement, nous ajoutons une fonction JavaScript supplémentaire qui est utilisée pour tester l'état du document. S'il est chargé, nous lançons un onPageLoaded()événement personnalisé dans Android MainActivity; sinon, nous enregistrons un écouteur d'événements qui met à jour Android une fois la page prête, en utilisant window.addEventListener('onload', ...);.

Étant donné que nous ajoutons ce script après l'appel à this.getWebView().loadURL(""), il est probable que nous n'ayons pas du tout besoin d' écouter les événements, car nous n'avons la possibilité d'ajouter le hook JavaScript qu'en effectuant un appel successif à loadURL, une fois la page déjà chargée.

Mapsy
la source
Solution géniale, qui fonctionne généralement. J'ai des problèmes avec https://reddit.com/r/Nature (avec Reddit en général), lorsque vous cliquez sur un fil et que le fil est chargé, je ne peux pas attraper cet événement. Peux-tu m'aider?
Primož Kralj
@ PrimožKralj Heureux d'apprendre que vous avez du succès avec cela ... Je ne sais pas quoi suggérer spécifiquement, mais s'il y a des événements publics que vous savez déclenchés auxquels vous pouvez vous connecter, par exemple lorsque le le nombre de commentaires est mis à jour, vous pouvez l'utiliser comme source. Avez-vous pensé que votre problème pourrait être résolu en appuyant directement sur l' API de Reddit ?
Mapsy
1
Merci, je vais revoir les événements déclenchés et essayer de me connecter à l'un d'eux. Je connais l'API et j'essaierai de mettre en œuvre une solution plus robuste en l'utilisant à l'avenir. Merci!
Primož Kralj
1

Juste pour montrer la barre de progression, les méthodes "onPageStarted" et "onPageFinished" suffisent; mais si vous souhaitez avoir un indicateur "is_loading" (avec des redirections de page, ...), ces méthodes peuvent être exécutées sans séquençage, comme "onPageStarted> onPageStarted> onPageFinished> onPageFinished".

Mais avec mon court test (testez-le vous-même.), La file d'attente des valeurs de la méthode "onProgressChanged" est "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);
    }
}

Définissez également " is_loading = false" à la fermeture de l'activité, s'il s'agit d'une variable statique, car l'activité peut être terminée avant la fin de la page.

Jalil Hamdollahi Oskouei
la source
0

Chargement de l'url avec SwipeRefreshLayoutet ProgressBar:

UrlPageActivity.java:

    WebView webView;
    SwipeRefreshLayout _swipe_procesbar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_url_page);


        String url = "http://stackoverflow.com/";

        _swipe_procesbar = (SwipeRefreshLayout)findViewById(R.id.url_path_swipe_procesbar);

        _swipe_procesbar.post(new Runnable() {
                                  @Override
                                  public void run() {
                                      _swipe_procesbar.setRefreshing(true);
                                  }
                              }
        );

        webView = (WebView) findViewById(R.id.url_page_web_view);
        webView.getSettings().setJavaScriptEnabled(true);

        webView.setWebViewClient(new WebViewClient() {
            public void onPageFinished(WebView view, String url) {
                _swipe_procesbar.setRefreshing(false);
                _swipe_procesbar.setEnabled(false);
            }
        });
        webView.loadUrl(url);
    }

activity_url_page.xml:

<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/url_path_swipe_procesbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context="com.test.test1.UrlPageActivity">


            <WebView
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:id="@+id/url_page_web_view" />
        </RelativeLayout>

</android.support.v4.widget.SwipeRefreshLayout>
Hamid
la source
0

Voici une méthode qui vous permet d'enregistrer un fichier Runnableà exécuter une fois qu'une adresse Web particulière a terminé le chargement. Nous associons chacun Runnableavec une URL correspondante Stringdans un Map, et nous utilisons le WebViewde getOriginalUrl()méthode pour choisir le rappel approprié.

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

}
Mapsy
la source
0

Le rendu ne terminera pas le rendu lorsque la méthode OnPageFinshed est appelée ou que la progression atteint 100%, les deux méthodes ne vous garantissent donc pas que la vue a été entièrement rendue.

Mais vous pouvez déterminer à partir de la méthode OnLoadResource ce qui a déjà été rendu et ce qui est toujours en cours de rendu. Et cette méthode est appelée plusieurs fois.

        @Override
        public void onLoadResource(WebView view, String url) {
            super.onLoadResource(view, url);
           // Log and see all the urls and know exactly what is being rendered and visible. If you wanna know when the entire page is completely rendered, find the last url from log and check it with if clause and implement your logic there.
            if (url.contains("assets/loginpage/img/ui/forms/")) {
                // loginpage is rendered and visible now.
               // your logic here.

            }
        }
shreedhar
la source
0

Utilisez cela, cela devrait aider .`var currentUrl = "google.com" var partOfUrl = currentUrl.substring (0, currentUrl.length-2)

webView.setWebViewClient (objet: 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.
}

// Vous devez également remplacer une autre méthode de remplacement pour les erreurs telles que onReceiveError pour voir comment toutes ces méthodes sont appelées les unes après les autres et comment elles se comportent lors du débogage avec un point d'arrêt. } `

Quelqu'un
la source
-1

pour les utilisateurs de Kotlin:

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

il y a beaucoup de méthodes que vous pouvez remplacer

Amin Keshavarzian
la source