2011-04-14 22 views
14

Tengo una aplicación con solo un componente WebView visible que se usa para mostrar algo de HTML generado dinámicamente (también se puede ejecutar Javascript). Está habilitado para el WebView.Android WebView - Configuración del foco del campo HTML usando Javascript

Para algunas páginas que estoy tratando de establecer el foco de uno de los cuadros de texto de entrada después de la carga de la página ha terminado - no a través de cuerpo onLoad(), pero no por una llamada JS después de la página ha terminado de cargar es decir, en onPageFinished(). La mayor parte del Javascript ejecuta bien

webview.loadURL("javascript:JSMethod();"); 

Pero cuando se utiliza la misma llamada para hacer una document.getElementById('text1').focus() - el cursor no alcanza el elemento pero el Soft Keyboard no saldrá. El mismo código de javascript cuando se ejecuta desde un botón en la página tiene el efecto deseado.

os adjunto el código fuente que tiene 3 botones

  1. Focus Text1 - Coloque el cursor sobre el texto1 y aparece el Softkeyboard.
  2. Java Focus Text1 - Llama a Java para ejecutar el mismo JS. Solo muestra el cursor allí y no aparece el teclado
  3. Java Focus Text1 And Keyboard Open - Llamadas JS desde Java y Forces Keyboard abiertas.

Mi entendimiento es que la ejecución de JS debería funcionar de la misma si se ejecuta desde el navegador mediante un botón/evento o como enviado desde Java a través WebView.loadURL().

Aquí está mi consultas

  1. Me estoy perdiendo algo cuando se utiliza Button#2? Así es como mi código actual es y solo veo que el cursor está configurado pero el SoftKeyboard no se abrirá.
  2. Cuando uso la lógica tal como está escrita en Button#3, algunas veces no veo el cursor en el campo pero me da el efecto deseado y el cursor se vuelve visible cuando escribo algo en el teclado emergente.
  3. ¿Podría el comportamiento que veo en Button#2 ser un error en la ejecución de Android JS? ¿O podría ser que el WebView no tiene foco, por eso solo se muestra el cursor? También probé webview.requestFocus() - No puedo escribir requestFocusOnTouch() ya que es la única Vista que tengo y espero que se centre automáticamente.

El código Java, que demos el comportamiento es

import android.app.Activity; 
    import android.content.Context; 
    import android.os.Bundle; 
    import android.util.Log; 
    import android.view.inputmethod.InputMethodManager; 
    import android.webkit.JsResult; 
    import android.webkit.WebChromeClient; 
    import android.webkit.WebView; 
    import android.webkit.WebViewClient; 

    public class WebViewProjectTestJSHTMLFocusActivity extends Activity { 

     Activity _current = null; 
     WebView wv = null; 

     /** Called when the activity is first created. */ 
     @Override 
     public void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
      _current = this; 
      //setContentView(R.layout.main); 
      String data = "<html><body>" + 
           "<script>function focusser() { document.getElementById(\"text1\").focus(); } </script>" + 
           "<script>function javaFocusser() { javautil.javaFocus(false); } </script>" + 
           "<script>function javaFocusserKeyboard() { javautil.javaFocus(true); } </script>" + 
           "Text 1<input type='text' id='text1'/><br/>" + 
           "Text 2<input type='text' id='text2'/><br/>" + 
           "<input type='button' value='Focus Text1' onClick='focusser()'/>" + 
           "<input type='button' value='Java Focus Text1' onClick='javaFocusser()'/>" + 
           "<input type='button' value='Java Focus Text1 And Keyboard Open' onClick='javaFocusserKeyboard()'/>" + 
          "</body></html>"; 
      wv = new WebView(this); 
      wv.getSettings().setJavaScriptEnabled(true); 

      // Set some HTML 
      wv.loadDataWithBaseURL("file:///android_asset/", data, "text/html", "UTF-8", null); 

      // Call back required after page load finished 
      wv.setWebViewClient(new CustomWebViewClient()); 

      // Enable Alert calls 
      wv.setWebChromeClient(new CustomWebChromeClient()); 

      // For JS->Java calls 
      wv.addJavascriptInterface(this, "javautil"); 

      setContentView(wv); 
     } 


     /** 
     * Calls the same javascript and forces the keyboard to open 
     */ 
     public void javaFocus(final boolean shouldForceOpenKeyboard) { 

      Thread t = new Thread("Java focusser thread") { 
       public void run() { 
        wv.loadUrl("javascript:focusser();"); 
        if(shouldForceOpenKeyboard) { 
         InputMethodManager mgr = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 
         mgr.showSoftInput(wv, InputMethodManager.SHOW_IMPLICIT); 
        } 
       } 
      }; 

      // Run on the View Thread. 
      _current.runOnUiThread(t); 
     } 

     /** 
     * Calls focus method after the page load is complete. 
     */ 
     final class CustomWebViewClient 
     extends WebViewClient { 
      @Override 
      public void onPageFinished(WebView view, String url) { 
       // javaFocus(true); 
       Log.d("TestExamples", "focusser call complete"); 
      } 
     } 

     final class CustomWebChromeClient 
     extends WebChromeClient { 
      @Override 
      public boolean onJsAlert(WebView view, String url, String message, JsResult result) { 
       Log.d("TestExamples", "JS Alert :: " + message); 
       return false; 
      } 
     } 
    } 

Solución actualización 24-06-2011 Para que esto funcione, es necesario utilizar wv.requestFocus(View.FOCUS_DOWN) justo antes de la llamada real enfoque JS. Modifiqué el método javaFocus() anterior a la versión correcta a continuación. Anteriormente, cuando mencioné que estaba usando requestFocus(), lo estaba usando cuando se inicializó WebView en el método onCreate(). La diferencia principal ahora es que forzamos el WebView para obtener el foco cada vez justo antes de que se ejecute el Javascript document.getElementById("text1").focus();.

public void javaFocus(final boolean shouldForceOpenKeyboard) { 
    Thread t = new Thread("Java focusser thread") { 
     public void run() { 
      wv.requestFocus(View.FOCUS_DOWN); 
      wv.loadUrl("javascript:focusser();"); 
      if(shouldForceOpenKeyboard) { 
       InputMethodManager mgr = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 
       mgr.showSoftInput(wv, InputMethodManager.SHOW_IMPLICIT); 
      } 
     } 
    }; 

    // Run on the View Thread. 
    _current.runOnUiThread(t); 
} 

también para asegurar que esta cuestión no se fija debido al enfoque activado mediante tacto, etc., estoy usando un subproceso de fondo para iniciar la javaFocus() después de 5 segundos de vista web visualizada. El onCreate() modificado está abajo.

..... More onCreate code before.... 
// Enable Alert calls 
wv.setWebChromeClient(new CustomWebChromeClient()); 

// For JS->Java calls 
wv.addJavascriptInterface(this, "javautil"); 

setContentView(wv); 

new Thread("After sometime Focus") { 
    public void run() { 
     try { 
      Thread.sleep(5000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     javaFocus(true); 
    } 
}.start(); 
.... onCreate() ends after this.... 
+0

Gracias por la explicación detallada. Tuve el mismo problema pero esta solución no funcionó para mí en Android 3.2. Al final tuve que escribir una función que simulara un toque real en el campo. No sé por qué tu solución no funcionó. El WebView está repleto de caprichos. – Pre101

+0

No probé este código en Android 3.x/4.x. Pero, ¿intentó ejecutar este programa de muestra en cualquiera de ellos? – Swaroop

+0

Me encantaría saber si puede usar este enfoque para asegurarse de que una entrada de tipo = número obtenga realmente un teclado numérico. Por lo que estoy obteniendo, InputMethodManager solo puede abrir el diseño de teclado estándar (Qwerty) ya que no sabe qué elemento HTML tiene foco actualmente. Usar wv.requestFocus no ayudó. – Wytze

Respuesta

5

Es posible que la vista web no tenga el foco de la aplicación. Intenta ejecutar;

wv.requestFocus(View.FOCUS_DOWN); 
+2

Esto realmente funcionó. El truco es usar 'wv.requestFocus (View.FOCUS_DOWN);' justo antes de solicitar Focus. Modificando la pregunta para que el código esté bien formateado. – Swaroop

+0

¡Feliz de ayudar! :) – Jivings

+0

cualquiera sabe dosis la respuesta wv.requestFocus (View.FOCUS_DOWN) ¿funciona en iOS? Gracias – star

Cuestiones relacionadas