Подтвердить что ты не робот

Есть ли слушатель, когда WebView отображает его содержимое?

Используя WebViewClient и/или WebChromeClient, вы можете получить прослушиватель для загрузки страницы, однако это иногда вызывается до того, как у WebView есть какой-либо контент в нем, прежде чем он что-нибудь отобразит.

Каким будет эффективный метод определения, когда WebView отобразил его содержимое?

Изменить: (Попытка быть более понятной)

Когда я загружаю страницу в WebView, я хочу установить прокрутку в определенную позицию. Кажется, что позиция прокрутки не может быть установлена ​​до тех пор, пока страница не будет загружена и не будет иметь фактическую высоту содержимого. Итак, я пробовал два разных подхода к определению того, когда страница закончила загрузку, onPageFinished() из WebViewClient, а также onProgressChanged() из WebChromeClient. Обе из них говорят мне, когда страница закончила загрузку.

Однако проблема заключается в том, что иногда она вызывается до того, как страница была отображена, и поэтому страница не имеет высоты, и вызов прокрутки ничего не делает.

Я пытаюсь найти надежный способ определить, когда страница готова к прокрутке, т.е. когда он имеет свою высоту содержимого.

Я предполагаю, что смогу настроить цикл проверки после того, как он закончил загрузку, чтобы продолжить поиск, когда высота будет доступна, но это похоже на хак. Надеясь, что есть более чистый способ.

4b9b3361

Ответ 1

Я успешно использовал Richard answer with PictureListener в течение нескольких лет, но я больше не рекомендую это как лучшее решение.

Это происходит по двум причинам:

  • webView.setPictureListener и PictureListener оба осуждается.
  • Использование этого прослушивателя заставит WebView часто выделять новое изображение. Это распределение дорогое, и это может иметь некоторые существенные последствия для производительности или даже привести к сбоям в работе на JellyBean MR1.

Вместо этого я рекомендую создать подкласс WebView и переопределить invalidate() следующим образом:

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

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

Если вы все еще хотите использовать метод PictureListener, вы получите лучшую производительность, если вы установите для параметраPictureListener значение null после того, как вы закончите с ним.

Ответ 2

EDIT: поскольку я впервые разместил это, этот метод устарел в Android API 12. Спасибо, Google! Я оставлю исходный ответ в тактике:


Да - есть слушатель, зная, когда содержимое закончило загрузку. Мне пришлось создать его в моем проекте, чтобы я мог сделать заставку, которая оставалась до тех пор, пока веб-просмотр не загрузил страницу.

Он вызвал .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.      
    }    
} 

Ответ 3

Предлагаемые решения здесь в лучшем случае взломаны, в то время как в соответствии с документами Android есть совершенно чистое решение :

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

Ответ 4

Я прочитал эту дискуссию, и я тоже сталкиваюсь с той же проблемой.

Я много искал, но они не являются решением, которым они обещают быть.

И я не хочу использовать устаревший обратный вызов onNewPicture.

В моей собственной ситуации мне нужно только восстановить позицию прокрутки "WebView" при запуске действия, и я думаю, что это больше всего случаев, когда стек стека активности переходит в фоновый режим, Android автоматически сохраняет состояние "WebView", поэтому, когда он появляется на переднем плане, он будет выглядеть одинаково. Если он будет удален из-под фона, я уверен, что вам удастся сохранить состояние в методах жизненного цикла активности, например `onPause`.

Итак, вместо расширения `WebView` и переопределения blah, blah, blah..., я использую модель 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, если это так, он выполняет прокрутку и удаляет обратный вызов, в противном случае он будет зациклен. Я проверяю это и узнаю, что он обычно не займет много времени.

Надеюсь, это поможет!

Ответ 5

Я создал настраиваемый вид, расширяющий webview, что переопределяет метод onSizeChanged. OnSizeChanged происходит после того, как webview загружает все в нем.

Ответ 6

EDIT: я больше не рекомендую это решение, но я оставлю его здесь для информации.

В случае, если это помогает кому-либо еще, способ, которым я это делал, заключался в подклассе WebView и переопределении метода computeVeritcalScrollExtent().

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

    return super.computeVerticalScrollExtent();
}

Это будет вызываться в любое время, когда WebView вычисляет свою вертикальную полосу прокрутки. Однако в первый раз, когда он вызывается где getContentHeight() > 0, то это будет первый раз, когда будет отображаться содержимое.

Ответ 7

Это не прямой ответ на заданный вопрос, но вы также можете использовать 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
    }
});

Ответ 8

Я знаю его Старый, но он может ПОМОЧЬ, ответы здесь не совсем работают, лучшее, что я нашел, это переопределить onDraw в расширенном WebView

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

            super.onDraw(canvas);
        }

поэтому каждая прокрутка вниз/вверх каждый fontZoomChange

почти все (не проверили все) вызовет onDraw

Я использую это, чтобы работать с SeekBar как Vertical ScrollBar

;)

его важно проверить, если null, и добавить некоторые другие, если во избежание бесполезного вызова метода

Ответ 9

Я исправил эту проблему, создав пользовательский вид, который переопределяет метод 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;
}   

Я думаю, что это не лучший способ сделать это, но он работает для моего приложения.

Ответ 10

onLoadResource(WebView view, String url)

Сообщите хост-приложению, что WebView загрузит ресурс, указанный данным URL.

Все еще не ясно, что цель здесь, но вы можете попробовать

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

Я бы "предположил", что страница завершила загрузку до ее добавления в историю...