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
Focus Text1
- Coloque el cursor sobre el texto1 y aparece el Softkeyboard.Java Focus Text1
- Llama a Java para ejecutar el mismo JS. Solo muestra el cursor allí y no aparece el tecladoJava 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
- 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á. - 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. - ¿Podría el comportamiento que veo en
Button#2
ser un error en la ejecución de Android JS? ¿O podría ser que elWebView
no tiene foco, por eso solo se muestra el cursor? También probéwebview.requestFocus()
- No puedo escribirrequestFocusOnTouch()
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....
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
No probé este código en Android 3.x/4.x. Pero, ¿intentó ejecutar este programa de muestra en cualquiera de ellos? – Swaroop
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