วิธีฟัง WebView ในการโหลด URL เสร็จสิ้นแล้ว?


447

ฉันมีสิ่งWebViewที่กำลังโหลดหน้าจากอินเทอร์เน็ต ฉันต้องการที่จะแสดงProgressBarจนกว่าการโหลดจะเสร็จสมบูรณ์

ฉันจะฟังเพื่อเสร็จสิ้นการโหลดหน้าWebView?


1
โปรดลองทำเครื่องหมายคำตอบของฉันให้ถูกต้องเพราะมันช่วยแก้ปัญหาที่เอียนไม่ได้
neteinstein

ฉันคิดว่าเป็นวิธีที่ดีกว่าในการโทรหารหัสภาษาจาวาด้วย js เมื่อโหลดหน้าเว็บ อ้างถึงคำตอบนี้แม้ว่าจะใช้กับ ios แต่แนวคิดก็มีผลเช่นกัน
Kris Roofe

ตรวจสอบคำตอบของฉันด้านล่างสำหรับวิธีการแก้ปัญหาที่น้อยและกระชับ
Skynet

คำตอบ:


716

ขยายWebViewClientและโทรonPageFinished () ดังต่อไปนี้:

mWebView.setWebViewClient(new WebViewClient() {

   public void onPageFinished(WebView view, String url) {
        // do your stuff here
    }
});

ฉันมีปัญหาบางอย่างกับการโหลดภายนอกเมื่ออินเทอร์เน็ตไม่เร็ว ตัวอย่างเช่น Google Analytics หรือเนื้อหาอื่น ๆ เช่นนั้น ฉันพยายามแก้ไขปัญหาบางอย่างและปรับปรุงให้ดีขึ้น แต่ยังไม่สมบูรณ์แบบ บางครั้งแอพจะหยุดการโหลดหน้าจอและเป็นไปไม่ได้ที่จะออกเว้นแต่คุณจะตัดการเชื่อมต่อเครือข่ายหรือเชื่อมต่อกับเครือข่ายอื่น ฉันยังไม่รู้วิธีแก้ปัญหานี้ แต่ฉันกำลังพยายาม
เฟลิเป้

1
ทำงานได้สมบูรณ์แบบ คุณสามารถใช้ mWebView.setVisibility (View.INVISIBLE) ก่อนที่จะโหลด เมื่อการโหลดเสร็จสมบูรณ์ให้ตั้งค่ากลับเป็น View.VISIBLE ฉันใช้มันกับหน้าจอเริ่มต้นนี้: android-developers.blogspot.de/2009/03/ …
Johan Hoeksma

39
นี่ไม่ใช่วิธีแก้ปัญหาเลย ไม่มีการรับประกันว่าหน้าจะโหลดแล้วเมื่อมีการเรียกใช้เมธอดนี้
Hawk

3
นี่เป็นการออกแบบที่ไม่ดีในส่วนของ Google เกือบตลอดเวลาเมื่อการกระทำนี้เสร็จสมบูรณ์คุณต้องการทำสิ่งที่มุ่งเน้นไปที่กิจกรรมหลักไม่ใช่มุมมองบนเว็บ การเอาชนะฟังก์ชั่นแทนการสมัครเข้าร่วมอีเวนต์เป็นรูปแบบการต่อต้านทั่วไปและเหตุผลที่ฉันไม่ชอบการพัฒนาแอนดรอยด์
Ryan

6
วิธีการนี้ไม่รับประกันการเสร็จสิ้นการโหลดและสามารถเรียกได้มากกว่าหนึ่งครั้งหากการโหลด URL ใช้การนำทาง URL ระดับกลาง นี่จึงถูกเรียกหลายครั้ง อย่างไรก็ตามมันเป็นวิธีการตรวจสอบ
เริ่มต้น

150

@ อันนี้ไม่ถูกต้อง 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; 
        }
    }
});

UPDATE:

ตามเอกสารประกอบ: onPageStarted จะไม่ถูกเรียกเมื่อเนื้อหาของเฟรมที่ฝังอยู่เปลี่ยนไปเช่นคลิกลิงค์ที่มีเป้าหมายคือ iframe

ฉันพบกรณีเฉพาะเช่นนั้นใน Twitter ซึ่งมีการเรียกเพจที่เสร็จสิ้นแล้วและทำให้ตรรกะสับสนเล็กน้อย เพื่อแก้ปัญหาที่ฉันเพิ่มงานที่กำหนดเวลาไว้เพื่อลบการโหลดหลังจาก X วินาที ไม่จำเป็นในกรณีอื่นทั้งหมด

อัปเดต 2 :

ขณะนี้มีการใช้งาน WebView สำหรับ Android ปัจจุบัน:

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

3
คุณอาจสังเกตุเห็นว่า caveat ในเอกสารของ onPageStarted: onPageStarted จะไม่ถูกเรียกเมื่อเนื้อหาของการเปลี่ยนแปลงเฟรมฝังตัวคือการคลิกลิงค์ที่มีเป้าหมายเป็น iframe ดังนั้นนี่อาจบิดเบือนตรรกะในกรณีเหล่านั้น BTW การลดความซับซ้อนของ @ polen ทำงานจริงหรือ
an00b

1
จับดีไม่เคยสังเกตสิ่งที่กรอบ ฉันไม่ได้ลองใช้รหัสของ polen .. สิ่งเดียวที่ฉันรับรองได้ว่างานมันเป็นสิ่งที่ฉันใช้
neteinstein

3
เพียงแค่การแก้ไขเล็กน้อย เป็นจริง "โมฆะสาธารณะ onPageStarted (มุมมอง WebView, String url, บิตแมป favicon)" แทน "โมฆะสาธารณะ onPageStarted (มุมมอง WebView, String url)"
MrMaffen

ใช้งานไม่ได้กับบางเว็บไซต์ที่ใหม่กว่าที่ไม่เคยโหลด ... เช่น "agoda.com" คุณไม่เคยได้รับสาย onPageFinished เพราะเป็นการเปลี่ยนเส้นทาง
kenyee

ฉันได้เห็นบนหน้าเสร็จถูกเรียกสองครั้งในระหว่างการเปลี่ยนเส้นทาง แต่สิ่งที่คุณพูดว่า "ถ้าคุณมีหลาย iframe ในหน้าคุณจะมีหลาย onPageFinished (และ onPageStarted)" ไม่ถูกต้องตามเอกสารของ onPageFinished: "วิธีนี้เรียกว่าสำหรับเฟรมหลักเท่านั้น"
โกเมน

40

ฉันค่อนข้างจะเป็นบ้าเป็นหลังกับโซลูชัน @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.
            }
        }
    });
}

2
รหัสคุณดูดี ฉันพยายามทำเหมือนกันสำหรับ webview ของฉันซึ่งโหลดจากข้อมูล html ไม่ใช่ url แต่อันนี้ทริกเกอร์ onPageFinished ถ้าโหลดเว็บวิวแรกอย่างรวดเร็วและก่อนที่อันที่สองเริ่มโหลด สถานการณ์ปกติ วิ่ง = 1, วิ่ง = 2, --running = 1, --running = 0 สถานการณ์ที่ผิดปกติที่ล้มเหลว - กำลังวิ่ง = 1, --running = 0, กำลังวิ่ง = 1 ที่ทำงาน = 0
Ajith Memana

1
นอกจากนี้ยังมีสถานการณ์อื่นเมื่อเหตุการณ์ไม่ได้ถูกยิงด้วยเหตุผลบางอย่างจะไม่มีการเข้าถึงส่วนที่ต้องทำ ดังนั้นคุณต้องมีตัวจับเวลาเพื่อตรวจสอบการหมดเวลา หรือคุณสามารถเรียกใช้ฟังก์ชันจาวาที่เอ็กซ์พอร์ตในจาวาสคริปต์เมื่อคุณรู้ว่าโหลดทุกอย่างถูกต้อง documentReady () หรืออะไรทำนองนั้น
Codebeat

ทำไมไม่เพียงrunning = 1;ในonPageStarted()?
Choletski

@Choletski เนื่องจากค่าสูงสุด 1 และจำนวนที่มากกว่า 1 ไม่ใช่ 1
Matthew Read

25

ฉันพบวิธีแก้ไขปัญหาที่หรูหราเช่นกันไม่ได้ทดสอบอย่างจริงจังว่า:

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

2
ฉันได้ทำการทดสอบแล้วและมันทำงานได้อย่างสมบูรณ์แบบคุณสามารถเรียกมันจากนอกวิธีการ onPageFinished และใช้ Handler เพื่อตรวจสอบในช่วงเวลาสั้น ๆ - ในกรณีที่คุณไม่ต้องการขยายคลาส WebViewClient
Gal Rom

1
ฉันเชื่อว่านี่อาจจะดีกว่าคำตอบที่ยอมรับคุณเพียงแค่ต้องตรวจสอบ onError และคุณตั้ง
Evin1_

1
นี่ควรเป็นคำตอบที่ยอมรับได้
زياد


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

        }
 });

มันง่ายที่จะเข้าใจ OnPageFinished ถ้าการเรียกกลับก่อนหน้านี้บน onPageStarted ดังนั้นหน้าจะโหลดอย่างสมบูรณ์


3
@polen PAGE_STARTED ไม่เคยถูกล้างออกหรือ เกิดอะไรขึ้นถ้า shouldOverrideUrlLoading () ไม่เคยถูกเรียก?
an00b

20

หากคุณต้องการแสดงแถบความคืบหน้าคุณจำเป็นต้องฟังเหตุการณ์การเปลี่ยนแปลงความคืบหน้าไม่ใช่เฉพาะสำหรับการทำหน้าให้สมบูรณ์:

mWebView.setWebChromeClient(new WebChromeClient(){

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

                //change your progress bar
            }


        });

BTW ถ้าคุณต้องการที่จะแสดงเพียง ProgressBar กำหนดไม่ได้แทนที่วิธีการบนหน้าเสร็จแล้วก็เพียงพอ



5

คุณสามารถติดตาม Progress Staus ได้โดยวิธีgetProgressในคลาสwebview

เริ่มต้นสถานะความคืบหน้า

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

mProgressStatus = webview.getProgress (); ต้องถูกเรียกจากเธรด UI
Skynet

5

ขอบคุณสำหรับคำตอบ มันช่วยฉันได้ แต่ฉันต้องปรับปรุงมันเล็กน้อยสำหรับความต้องการของฉัน ฉันมี pagestarts หลายแห่งและเสร็จสิ้นดังนั้นฉันจึงเพิ่มตัวจับเวลาซึ่งตรวจสอบว่าการเรียงหน้าเพจเริ่มต้นเป็น pagestart ใหม่หรือไม่ ตกลงคำอธิบายที่ไม่ดี ดูรหัส :)

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

});

2

นี่เป็นวิธีการใหม่สำหรับการตรวจพบเมื่อมีการโหลด URL โดยใช้ความสามารถของ Android สำหรับตะขอ การใช้รูปแบบนี้เราใช้ประโยชน์จากความรู้ของ JavaScript เกี่ยวกับสถานะของเอกสารเพื่อสร้างการเรียกใช้เมธอดแบบเนทีฟภายในรันไทม์ Android การโทรที่สามารถเข้าถึง JavaScript เหล่านี้สามารถทำได้โดยใช้@JavaScriptInterfaceคำอธิบายประกอบ

การใช้งานนี้ต้องการให้เราเรียกsetJavaScriptEnabled(true)การWebViewตั้งค่าของดังนั้นจึงอาจไม่เหมาะสมขึ้นอยู่กับข้อกำหนดของแอปพลิเคชันของคุณเช่นความกังวลด้านความปลอดภัย

src / io / github / cawfree / webviewcallback / MainActivity.java (Jelly Bean, API ระดับ 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;
    }

}

ความละเอียด / รูปแบบ / 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"
/>

โดยพื้นฐานแล้วเรากำลังผนวกฟังก์ชั่น JavaScript เพิ่มเติมที่ใช้ในการทดสอบสถานะของเอกสาร ถ้ามันโหลดเราเปิดตัวเองonPageLoaded()ในกรณีของ Android MainActivity; มิฉะนั้นเราลงทะเบียนฟังเหตุการณ์ที่ปรับปรุง Android window.addEventListener('onload', ...);ละครั้งหน้าพร้อมใช้

เนื่องจากเรากำลังต่อท้ายสคริปต์นี้หลังจากมีการโทรออกthis.getWebView().loadURL("")จึงเป็นไปได้ที่เราไม่จำเป็นต้อง'ฟัง'สำหรับกิจกรรมเลยเนื่องจากเราจะได้รับโอกาสต่อท้าย JavaScript hook โดยการโทรติดต่อกันเพื่อloadURLเมื่อหน้าถูกโหลดแล้ว


ทางออกที่ยอดเยี่ยมซึ่งใช้งานได้โดยทั่วไป ฉันมีปัญหากับhttps://reddit.com/r/Nature (โดยทั่วไป Reddit) เมื่อคุณคลิกที่เธรดและโหลดเธรดฉันไม่สามารถจับเหตุการณ์นั้นได้ คุณช่วยฉันออก
Primož Kralj

@ PrimožKraljดีใจที่ได้ทราบว่าคุณมีบางความสำเร็จกับการนี้ ... ผมไม่แน่ใจว่าสิ่งที่จะแนะนำเฉพาะ แต่ถ้ามีชนิดของกิจกรรมสาธารณะที่คุณรู้ว่าจะถูกเรียกว่าคุณสามารถขอเข้ามาเช่นเมื่อใด อัปเดตการนับความคิดเห็นแล้วคุณสามารถใช้เป็นแหล่งที่มาได้ คุณได้พิจารณาแล้วว่าปัญหาของคุณอาจแก้ไขได้ด้วยการกดปุ่มAPIของ Reddit โดยตรง
Mapsy

1
ขอบคุณฉันจะดูเหตุการณ์ที่เกิดขึ้นอีกครั้งและพยายามขอหนึ่งในนั้น ฉันรับรู้ถึง API และจะพยายามใช้โซลูชันที่มีประสิทธิภาพมากขึ้นในอนาคต ขอบคุณ!
Primož Kralj

1

เพียงแสดงแถบความคืบหน้าเมธอด "onPageStarted" และ "onPageFinished" ก็เพียงพอแล้ว แต่ถ้าคุณต้องการให้มีการตั้งค่าสถานะ "is_loading" (พร้อมกับการเปลี่ยนเส้นทางหน้า, ... ) วิธีการนี้อาจดำเนินการโดยไม่เรียงลำดับเช่น "onPageStarted> onPageStarted> onPageFinished> onPageFinished" คิว

แต่ด้วยการทดสอบสั้น ๆ ของฉัน (ทดสอบด้วยตัวเอง) คิว "onProgressChanged" ค่าคิวคือ "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);
    }
}

นอกจากนี้ยังตั้งค่า " is_loading = false" เมื่อปิดกิจกรรมหากเป็นตัวแปรคงที่เพราะกิจกรรมสามารถเสร็จสิ้นก่อนที่หน้าจะเสร็จสิ้น


0

กำลังโหลด URL ด้วยSwipeRefreshLayoutและ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>

0

ต่อไปนี้เป็นวิธีการที่ช่วยให้คุณสามารถลงทะเบียน a Runnableเพื่อดำเนินการได้เมื่อที่อยู่เว็บหนึ่งโหลดเสร็จแล้ว เราเชื่อมโยงแต่ละRunnableที่มี URL ที่สอดคล้องกันStringในMapและเราใช้WebView's getOriginalUrl()วิธีการที่จะเลือกการเรียกกลับที่เหมาะสม

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

ตัวแสดงผลจะไม่เสร็จสิ้นการแสดงผลเมื่อมีการเรียกใช้เมธอด OnPageFinshed หรือความคืบหน้าถึง 100% ดังนั้นทั้งสองวิธีจึงไม่รับประกันว่ามุมมองนั้นจะได้รับการแสดงผลอย่างสมบูรณ์

แต่คุณสามารถคิดออกจากวิธี OnLoadResource สิ่งที่ได้รับการแสดงผลแล้วและสิ่งที่ยังคงแสดงผล และวิธีนี้ถูกเรียกหลายครั้ง

        @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.

            }
        }

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

// คุณควรแทนที่เมธอด override อื่น ๆ เพื่อหาข้อผิดพลาดเช่น onReceiveError เพื่อดูว่าวิธีการเหล่านี้ถูกเรียกใช้อย่างใดอย่างหนึ่งหลังจากที่อื่นและวิธีการที่พวกเขาทำงานในขณะที่การดีบักด้วยจุดพัก } `


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.