WebView显示内容时是否有监听器?

使用WebViewClient和/或WebChromeClient,您可以获取页面加载时的监听器,但在WebView显示任何内容之前,有时会调用此监听器。

什么是确定WebView何时显示内容的有效方法?

编辑:(试图更清楚)

当我在WebView中加载页面时,我想将滚动设置为特定的位置。 看来,滚动的位置不能设置,直到页面加载,它有一个实际的内容高度。 所以,我已经尝试了两种不同的方法来确定页面何时完成加载,来自WebViewClient的onPageFinished()以及WebChromeClient的onProgressChanged()。 这两个告诉我什么时候页面完成加载。

但是,问题在于有时会在页面显示前被调用,因此页面没有高度,滚动调用什么也不做。

我试图find一个坚实的方式来确定页面准备好滚动,即。 当它有内容的高度。

我想我可以设置一个检查循环完成加载后,继续寻找何时可用的高度,但这似乎相当黑客。 希望有一个更清洁的方式。

我已经成功地将Richard的答案与PictureListener一起使用了几年,但我不再推荐这是最好的解决scheme。

这是有两个原因的:

  1. webView.setPictureListener和PictureListener都被弃用。
  2. 使用这个监听器会导致WebView经常分配一个新的图片。 这个分配是昂贵的,这可能会有一些显着的性能影响,甚至导致JellyBean MR1本地崩溃。

相反,我build议创build一个WebView的子类和重写invalidate()像这样:

@Override public void invalidate() { super.invalidate(); if (getContentHeight() > 0) { // WebView has displayed some content and is scrollable. } } 

如果您仍然想要使用PictureListener方法,则在完成该操作后,如果将SetPictureListener重新设置为null,将会获得更好的性能。

编辑:自从我第一次发布这个,这个方法已被弃用在Android API 12.谢谢,谷歌! 我会留下原来的答案:


是的 – 有一个听众知道内容何时完成加载。 我不得不在我的项目上创build一个,所以我可以做一个启animation面,直到webview加载页面。

它叫做.setPictureListener。

例如:

 mWebView.setPictureListener(new MyPictureListener()); //... and then later on.... class MyPictureListener implements PictureListener { @Override public void onNewPicture(WebView view, Picture arg1) { // put code here that needs to run when the page has finished loading and // a new "picture" is on the webview. } } 

根据Android文档 ,这里build议的解决scheme充其量只是简单的,而有一个完美的解决scheme:

 WebViewClient client = new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { Log.d("MYAPP", "Page loaded"); } }; webView.setWebViewClient(client); 

我读了这个讨论,我也面临同样的问题。

我search了很多,但他们不是他们承诺的解决scheme。

我不想使用不赞成的`onNewPicture`callback。

在我自己的情况下,我只需要在活动开始时恢复“WebView”滚动位置,我认为这是大部分情况,因为当活动任务堆栈进入后台时,Android会自动保存“WebView”状态,它popup到前景,它看起来是一样的。 如果它在后台被杀害,我相信你会设法保存在像“onPause”这样的Activity生命周期方法中。

所以,我没有使用WebView,而是使用Handler和Post模型。

 private final Handler mHandler = new Handler(); // in onCreate mHandler.postDelayed(new Runnable() { @Override public void run() { if (mWebView.getContentHeight() > 0) { mWebView.scrollTo(0, mLastPosition); Log.d("scrolling", "true"); mHandler.removeCallbacks(this); } else { mHandler.postDelayed(this, 100); } } }, 100); 

这个代码块会定期检查WebView页面是否可以被操纵,如果是,它会滚动并删除callback,否则会循环。 我testing这个,发现它通常不会花很长时间。

希望这可以帮助!

我创build了一个自定义视图扩展webview,它覆盖了“onSizeChanged”方法。 onSizeChanged发生在webview加载所有内容之后。

编辑:我不再推荐这个解决scheme,但我会留在这里为了信息的缘故。

如果这有助于其他人,我最终这样做的方式是通过computeVeritcalScrollExtent() WebView并重写computeVeritcalScrollExtent()方法。

 @Override protected int computeVerticalScrollExtent() { // do you checking here return super.computeVerticalScrollExtent(); } 

这将在WebView计算其垂直滚动条时随时调用。 但是,第一次调用getContentHeight() > 0 ,那么这将是第一次显示内容。

这不是问题的直接答案,但可以使用WebChromeClient。 我觉得它更可靠,我已经configuration为显示加载进度。 在页面完全加载之前,WebView隐藏ProgressBar时,我遇到了同样的问题,我用WebView客户端replace了WebView。

我使用下面的代码

 final WebView wvMax = (WebView) findViewById(R.id.webViewTnSmax); final ProgressBar pbMax = (ProgressBar) findViewById(R.id.progressBarTnSmax); wvMax.setWebChromeClient(new WebChromeClient() { public void onProgressChanged(WebView view, int progress) { pbMax.setVisibility(View.VISIBLE); pbMax.setProgress(progress); if (progress == 100) { pbMax.setVisibility(View.GONE); // Make the bar disappear after URL is loaded } } public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { // do something } }); 

我知道它的旧,但它可以帮助,这里的答案不完美的工作,我发现最好的是覆盖扩展WebView上的onDraw

  @Override protected void onDraw(Canvas canvas) { //do your math/stuff/magic/blackmagic/hackish here super.onDraw(canvas); } 

所以每次向下滚动/向上滚动每个fontZoomChange

几乎所有的东西(没有testing所有)将打电话给onDraw

我用它来作为一个SeekBar垂直滚动条

;)

其重要的是检查是否为null,并添加一些其他的如果避免无用的方法调用

我已经修复了这个问题,创build一个自定义视图,它覆盖onDraw方法并调用我自己的侦听器。 这是代码:

 public class CustomWebView extends WebView{ public interface FinishedDrawListener{ void onDrawFinished(WebView view, String url); } private FinishedDrawListener drawListener; public CustomWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } public CustomWebView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public CustomWebView(Context context, AttributeSet attrs) { super(context, attrs); } public CustomWebView(Context context) { super(context); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if(drawListener != null){ drawListener.onDrawFinished(this, this.getUrl()); } } public void setOnFinishedDrawListener(FinishedDrawListener listener){ this.drawListener = listener; } 

我认为这不是最好的办法,但它适用于我的应用程序。

 onLoadResource(WebView view, String url) 

通知宿主应用程序,WebView将加载由给定url指定的资源。

仍然不清楚这里的目标是什么,但是你可以试试

 public void doUpdateVisitedHistory (WebView view, String url, boolean isReload) 

我会“假设”该页面已经完成加载之前,它被添加到历史logging…

它在所有设备上工作正常: – 加载Web视图ProgressDialog