使用WebViewClient和/或WebChromeClient,您可以在页面加载时获取侦听器,但有时在WebView中显示任何内容之前调用它,然后才显示任何内容。
确定WebView何时显示内容的有效方法是什么?
编辑:(试图更清楚)
当我在WebView中加载页面时,我想将滚动设置为特定位置。看起来在页面加载之前无法设置滚动位置,并且它具有实际的内容高度。因此,我尝试了两种不同的方法来确定页面何时完成加载,来自WebViewClient的onPageFinished()以及来自WebChromeClient的onProgressChanged()。这两个都告诉我页面何时加载完毕。
然而,问题是有时它会在页面显示之前被调用,因此页面没有高度,滚动调用什么都不做。
我正在尝试找到一种可靠的方法来确定页面何时可以滚动,即。当它有内容高度时。
我想我可以在完成加载后设置一个检查循环,以便在高度可用时继续查找,但这看起来很像黑客。希望有一种更清洁的方式。
答案 0 :(得分:38)
我成功使用了Richard's answer with a PictureListener几年,但我不再推荐这是最佳解决方案。
这有两个原因:
相反,我建议创建WebView的子类并覆盖invalidate(),如下所示:
@Override
public void invalidate() {
super.invalidate();
if (getContentHeight() > 0) {
// WebView has displayed some content and is scrollable.
}
}
如果您仍想使用PictureListener方法,那么在完成后将setPictureListener恢复为null将获得更好的性能。
答案 1 :(得分:13)
是 - 有一个监听器知道内容何时完成加载。我不得不在我的项目中创建一个,所以我可以做一个启动画面,直到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.
}
}
答案 2 :(得分:9)
这里建议的解决方案充其量只是hacky,而有一个非常干净的解决方案,in accordance with the Android docs:
WebViewClient client = new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
Log.d("MYAPP", "Page loaded");
}
};
webView.setWebViewClient(client);
答案 3 :(得分:6)
我读了这个讨论,我也遇到了同样的问题。
我搜索了很多,但他们不是他们承诺的解决方案。
我不想使用已弃用的`onNewPicture`回调。
在我自己的情况下,我只需要在活动开始时恢复`WebView`滚动位置,我认为这是大多数情况,因为当活动任务堆栈进入后台时,Android会自动保存`WebView`状态,所以当它弹出到前景时,它看起来会一样。如果它在后台被杀死,我相信你会设法将状态保存在像`onPause`这样的Activity生命周期方法中。
所以,不是扩展`WebView`而是覆盖blah,blah,blah ......,而是使用Handler并发布模型。
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);
此代码块将进行peridically检查是否可以操作WebView页面,如果是,它会进行滚动并删除回调,否则循环。 我对此进行测试并发现它通常不会花很长时间。
希望这有帮助!
答案 4 :(得分:2)
我创建了一个自定义视图扩展webview,它覆盖了“onSizeChanged”方法。在webview加载其中的所有内容后,会发生onSizeChanged。
答案 5 :(得分:1)
编辑:我不再推荐此解决方案,但我会将其留在此处以供参考。
如果这对其他人有帮助,我最终这样做的方法是通过继承WebView并覆盖computeVeritcalScrollExtent()
方法。
@Override
protected int computeVerticalScrollExtent() {
// do you checking here
return super.computeVerticalScrollExtent();
}
只要WebView计算其垂直滚动条,就会调用此方法。但是,第一次调用getContentHeight() > 0
时,这将是第一次显示内容。
答案 6 :(得分:1)
这不是问题的直接答案,但您也可以使用WebChromeClient。我发现它更可靠,我已将其配置为显示加载进度。在页面完全加载之前,WebView隐藏了ProgressBar,我遇到了同样的问题,我用WebView客户端替换了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
}
});
答案 7 :(得分:1)
我知道它的旧但它可以帮助,这里的答案并不完美,我找到的最好的是在扩展的WebView上覆盖onDraw
@Override
protected void onDraw(Canvas canvas) {
//do your math/stuff/magic/blackmagic/hackish here
super.onDraw(canvas);
}
所以每次向下滚动/向上滚动 每个fontZoomChange
几乎所有的东西(没有全部测试过)都会调用onDraw
我使用它来处理SeekBar作为Vertical ScrollBar
)
检查是否为null很重要,如果要避免无用的方法调用,则添加其他一些
答案 8 :(得分:1)
我已经修复了这个问题,创建了一个自定义视图,它覆盖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;
}
我认为这不是最好的方法,但它适用于我的应用程序。
答案 9 :(得分:0)
onLoadResource(WebView view, String url)
通知主机应用程序WebView将加载由给定URL指定的资源。
还不清楚目标是什么,但你可以试试
public void doUpdateVisitedHistory (WebView view, String url, boolean isReload)
我会“假设”页面在添加到历史记录之前已完成加载...
答案 10 :(得分:-1)
它适用于所有设备: - Load Web View ProgressDialog