Is there a listener for when the WebView displays

2019-01-03 09:09发布

Using WebViewClient and/or the WebChromeClient you can get a listener for when the page has loaded, however this is sometimes called before the WebView has any content in it, before it has displayed anything.

What would be a efficient method for determining when the WebView has displayed it's content?

Edit: (Trying to be more clear)

When I load a page in a WebView, I want to set the scroll to a specific position. It seems that the scroll position cannot be set until the page is loaded and it has an actual content height. So, I have tried two different approaches to determining when the page has finished loading, onPageFinished() from the WebViewClient and also onProgressChanged() from the WebChromeClient. Both of these tell me when the page has finished loading.

However, the problem is that sometimes it is called before the page has been displayed and therefore the page has no height and the scroll call does nothing.

I am trying to find a solid way to determine when the page is ready to be scrolled, ie. when it has its content height.

I imagine I could setup a checking loop after it finished loading to keep looking for when the height is available but that seemed like quite the hack. Hoping there is a cleaner way.

11条回答
Animai°情兽
2楼-- · 2019-01-03 09:45

I successfully used Richard's answer with a PictureListener for a few years, but I no longer recommend this as the best solution.

This is for two reasons:

  1. webView.setPictureListener and PictureListener are both deprecated.
  2. Using this listener will cause the WebView to allocate a new Picture often. This allocation is expensive and this can have some significant performance impacts or even cause native crashes on JellyBean MR1.

Instead I recommend creating a subclass of WebView and overriding invalidate() like so:

@Override
public void invalidate() {
    super.invalidate();

    if (getContentHeight() > 0) {
        // WebView has displayed some content and is scrollable.
    }
}

If you still want to use the PictureListener method, you will get better performance if you setPictureListener back to null after you are done with it.

查看更多
啃猪蹄的小仙女
3楼-- · 2019-01-03 09:49

I Know its Old but it can HELP, the answers here are not perfectly working, the best that i found is to Override the onDraw on the Extended WebView

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

            super.onDraw(canvas);
        }

so every scroll down/up every fontZoomChange

almost everything(didnt tested all) will call the onDraw

i use this to work with a SeekBar as Vertical ScrollBar

;)

its important to check if null, and add some others if to avoid useless method call

查看更多
看我几分像从前
4楼-- · 2019-01-03 09:50

The suggested solutions here are hacky at best, while there is a perfectly clean solution, 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);
查看更多
ら.Afraid
5楼-- · 2019-01-03 09:54

EDIT: I no longer recommend this solution, but I'll leave it here for the sake of information.

In case this helps anyone else, the way I ended up doing this was by subclassing the WebView and overriding the computeVeritcalScrollExtent() method.

@Override
protected int computeVerticalScrollExtent() {
    // do you checking here

    return super.computeVerticalScrollExtent();
}

This will be called anytime the WebView calculates its vertical scrollbar. However, the first time it is called where the getContentHeight() > 0, then that will be the first time the content is displayed.

查看更多
爷的心禁止访问
6楼-- · 2019-01-03 09:54

I've fixed this issue creating a Custom View which overrides onDraw method and calling my own listener. This is the code:

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

I think that it's not the best way to do it but it works for my application.

查看更多
我只想做你的唯一
7楼-- · 2019-01-03 09:57
onLoadResource(WebView view, String url)

Notify the host application that the WebView will load the resource specified by the given url.

Still not clear of what the objective is here, but you might try

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

I would "assume" that the page has completed loading before it is added to history...

查看更多
登录 后发表回答