¿Hay un oyente para cuando el WebView muestra su contenido?

Utilizando WebViewClient y / o WebChromeClient puede obtener un oyente para cuando la página se ha cargado, sin embargo esto a veces se llama antes de que WebView tenga contenido en él, antes de que haya mostrado nada.

¿Cuál sería un método eficiente para determinar cuándo el WebView ha mostrado su contenido?

Editar: (Tratando de ser más claro)

Cuando cargue una página en un WebView, quiero configurar el desplazamiento a una posición específica. Parece que la posición de desplazamiento no se puede establecer hasta que la página se carga y tiene una altura de contenido real. Por lo tanto, he intentado dos enfoques diferentes para determinar cuándo la página ha terminado de cargar, onPageFinished () desde WebViewClient y también onProgressChanged () desde WebChromeClient. Ambos me dicen cuando la página ha terminado de cargar.

Sin embargo, el problema es que a veces se llama antes de la página se ha mostrado y por lo tanto la página no tiene altura y la llamada de desplazamiento no hace nada.

Estoy tratando de encontrar una manera sólida para determinar cuándo la página está lista para ser desplazado, es decir. Cuando tiene su altura de contenido.

Me imagino que podría configurar un bucle de control después de terminar de cargar para seguir buscando cuando la altura está disponible, pero que parecía ser bastante el hack. Esperando que haya una manera más limpia.

Utilicé con éxito la respuesta de Richard con un PictureListener durante unos años, pero ya no recomiendo esto como la mejor solución.

Esto es por dos razones:

  1. WebView.setPictureListener y PictureListener están obsoletos.
  2. El uso de este listener hará que WebView asigne una nueva imagen frecuentemente. Esta asignación es costosa y esto puede tener algunos impactos significativos en el rendimiento o incluso causar fallos nativos en JellyBean MR1.

En su lugar, recomiendo crear una subclase de WebView y sobreescribir invalidate () de la siguiente manera:

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

Si todavía desea utilizar el método PictureListener, obtendrá un mejor rendimiento si vuelve a establecer nulo después de que SetPictureListener haya terminado con él.

EDIT: Desde que publiqué por primera vez, este método ha quedado obsoleto en Android API 12. Gracias, Google! Voy a dejar la respuesta original en tacto:


Sí – hay un oyente para saber cuando el contenido ha terminado de cargar. Tuve que crear uno en mi proyecto para que pudiera hacer una pantalla de bienvenida que se quedó hasta que la webview había cargado la página.

Se llama .setPictureListener.

Por ejemplo:

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

Las soluciones sugeridas aquí son hacky en el mejor de los casos, mientras que hay una solución perfectamente limpia, de acuerdo con los documentos Android :

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

He leído esta discusión, y estoy enfrentando el mismo problema también.

Busqué mucho, pero no son la solución que prometen ser.

Y no quiero usar la devolución de llamada `onNewPicture` obsoleta.

En mi propia situación sólo necesito restaurar la posición de desplazamiento de 'WebView` cuando se inicia la actividad, y creo que este es el mayor número de casos ya que cuando la pila de tareas de actividad pasa al fondo, Android automáticamente guarda el estado `WebView`, Aparece en primer plano, se verá igual. Si se mata cuando está en segundo plano, estoy seguro de que se las arreglará para guardar el estado en los métodos de ciclo de vida de actividad como `onPause`.

Por lo tanto, en lugar de extender `WebView` y sobreescribir bla, bla, bla …, utilizo un manejador y un modelo de correos.

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

Este bloque de código peridically comprueba si la página WebView puede ser manipulada, si es así, hace el desplazamiento y quitar la devolución de llamada, de lo contrario lo bucles. Pruebo esto y lo averiguo ususally no tomará mucho tiempo.

¡Espero que esto ayude!

He creado una vista personalizada extiende webview, que anula el método "onSizeChanged". El onSizeChanged sucede después de que la webview cargue todo en él.

EDIT: Ya no recomiendo esta solución, pero la dejaré aquí por el bien de la información.

En caso de que esto ayude a alguien más, la forma en que acabé haciendo esto fue subclasificando el WebView y reemplazando el método computeVeritcalScrollExtent() .

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

Esto se llamará cada vez que WebView calcula su barra de desplazamiento vertical. Sin embargo, la primera vez que se llama donde getContentHeight() > 0 , entonces será la primera vez que se muestra el contenido.

Esto no es una respuesta directa a la pregunta, pero también puede utilizar WebChromeClient. Me resulta más confiable y lo he configurado para mostrar el progreso de carga. Tenía el mismo problema con WebView ocultando el ProgressBar antes de que la página estuviera completamente cargada y reemplazé WebView con el cliente WebView.

Yo uso el siguiente código

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

Sé que es viejo, pero puede ayudar, las respuestas aquí no funcionan perfectamente, lo mejor que he encontrado es sobreescribir el onDraw en el Extended WebView

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

Así que cada desplazamiento abajo / arriba cada fontZoomChange

Casi todo (no probado todo) llamará a la onDraw

Yo uso esto para trabajar con un SeekBar como Vertical ScrollBar

😉

Es importante comprobar si nulo, y añadir algunos otros si para evitar el método inútil de llamada

He arreglado este problema creando una vista personalizada que reemplaza el método onDraw y llama a mi propio detector. Este es el código:

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

Creo que no es la mejor manera de hacerlo, pero funciona para mi aplicación.

 onLoadResource(WebView view, String url) 

Notificar a la aplicación host que WebView cargará el recurso especificado por la url dada.

Todavía no está claro cuál es el objetivo aquí, pero puede intentar

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

Yo "asumiría" que la página ha completado la carga antes de que se agregue a la historia …

Su funcionamiento muy bien en todos los dispositivos: – Load Web View ProgressDialog

  • ¿Hay problemas en la vista Web de Android para SVG? Nivel API 16 +
  • Ajuste del tamaño dinámico del diseño en Android
  • Cambiar el color de resaltado de la vista web de Android del enlace
  • Color del enlace de Android WebView
  • ¿Cuál es el equivalente de "android: windowSoftInputMode" para un sitio web?
  • Android WebView: amplía el zoom a una escala específica después de cargar el contenido
  • Volver a llamar a Android WebView JavaScript a la vista original
  • WebView no está llenando toda la pantalla del dispositivo o el emulador
  • Uso del botón Atrás en una vista web en Android
  • Obtener el historial de WebView de WebBackForwardList
  • Método recomendado para presentar texto con formato en Android?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.