我有一个WebView正在从互联网加载一个页面。我想显示一个ProgressBar,直到加载完成。
我如何监听WebView页面加载的完成?
我有一个WebView正在从互联网加载一个页面。我想显示一个ProgressBar,直到加载完成。
我如何监听WebView页面加载的完成?
当前回答
当onpagefinished方法被调用或者进度达到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.
}
}
其他回答
如果你想显示一个进度条,你需要监听一个进度变化事件,而不仅仅是页面的完成:
mWebView.setWebChromeClient(new WebChromeClient(){
@Override
public void onProgressChanged(WebView view, int newProgress) {
//change your progress bar
}
});
顺便说一句,如果你只想显示一个覆盖onPageFinished方法的Indeterminate ProgressBar就足够了
扩展WebViewClient并调用onPageFinished()如下所示:
mWebView.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
// do your stuff here
}
});
谢谢你的回答。它帮助了我,但我必须根据我的需要稍加改进。我有几个页面开始和结束,所以我添加了一个定时器,检查是否在页面结束后开始一个新的页面开始。好吧,糟糕的解释。请参阅代码:)
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);
}
}
});
我发现了一个优雅的解决方案,虽然没有严格测试:
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (webView.getProgress() == 100) {
progressBar.setVisibility(View.GONE);
webView.setVisibility(View.VISIBLE);
}
}
这里有一个方法,它允许你注册一个Runnable,一旦一个特定的网页地址完成加载就会被执行。我们将每个可运行对象与Map中对应的URL字符串相关联,并使用WebView的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;
}
}