Android WebView - Réglage du Champ HTML focus à l'aide de Javascript

J'ai une application avec seulement visible WebView composant qui est utilisé pour afficher du contenu HTML généré dynamiquement (peut exécuter Javascript trop). Il est activé pour le WebView.

De quelques pages, je suis en train de mettre au centre d'une des zones de texte d'entrée après le chargement de la page a fini de - pas par Corps onLoad(), mais plutôt par un JS appel après que la page a fini de se charger, c'est à dire dans onPageFinished(). La plupart des javascript s'exécute fine

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

Mais quand j'utilise le même appel à un document.getElementById('text1').focus() - le curseur ne atteindre l'élément, mais l' Soft Keyboard ne sera pas pop. Le même code javascript lorsqu'il est exécuté à partir d'un bouton sur la page n'ont pas l'effet désiré.

Je joins le code source qui a 3 boutons

  1. Focus Text1 - Placez le curseur sur le texte1 et ouvre les Softkeyboard.
  2. Java Focus Text1 - Appels Java pour exécuter la même JS. Affiche uniquement le curseur là et de ne pas sortir le clavier
  3. Java Focus Text1 And Keyboard Open - Appels JS à partir de Java et les Forces de Clavier ouvert.

Ma compréhension est que le JS exécution devrait fonctionner de la même si exécuté à partir du navigateur à l'aide d'un bouton/événement ou envoyé à partir de Java par le biais de WebView.loadURL().

Voici mon Requêtes

  1. Suis-je raté quelque chose lors de l'utilisation de Button#2? Voilà comment mon code et je ne vois que le curseur est fixé, mais le SoftKeyboard ne s'ouvre pas.
  2. Lorsque j'utilise la logique comme écrit dans Button#3, j'ai quelques fois de ne pas voir le curseur sur le champ, mais me donne l'effet désiré et le curseur devient visible quand je tape quelque chose dans la sauté vers le haut du clavier.
  3. Pourrait le comportement que je vois dans Button#2 être un bug sur Android JS exécution? Ou se pourrait-il que le WebView n'ont pas d'accent c'est pourquoi seul le curseur est affiché? J'ai aussi essayé webview.requestFocus() - je ne peux pas écrire requestFocusOnTouch() que c'est le seul point de Vue que j'ai, et j'en attends, c'est centrée automatiquement.

Le code Java qui fait la démonstration du comportement est

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

Solution De Mise À Jour 24-06-2011
Pour ce faire, vous devez utiliser wv.requestFocus(View.FOCUS_DOWN) juste avant le JS se concentrer appel. J'ai modifié le javaFocus() méthode ci-dessus pour la version correcte ci-dessous. Plus tôt, quand j'ai mentionné que j'ai été en utilisant requestFocus(), j'ai été en utilisant que lorsque le WebView a été initialisé dans la méthode onCreate(). La principale différence est que nous sommes maintenant en forçant le WebView pour obtenir le focus à chaque fois juste avant le Javascript document.getElementById("text1").focus(); est exécutée.

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

Également de s'assurer que ce problème n'était pas résolu grâce à des focus déclenchée par le toucher, etc, je suis en utilisant un thread d'arrière-plan pour lancer le javaFocus() après 5 secondes de WebView Affiche. La modification de onCreate() est ci-dessous.

..... 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.... 
Merci pour l'explication approfondie. J'ai eu le même problème, mais cette solution n'a pas fonctionné pour moi sur Android 3.2. En fin de compte, j'ai dû écrire une fonction qui a simulé une réelle tapez sur le champ. Je ne sais pas pourquoi votre solution n'a pas fonctionné. La WebView est juste bourré de manies.
Je n'ai pas testé ce code dans Android 3.x/4.x. Mais avez-vous essayez d'exécuter cet exemple de programme dans l'un ou l'autre?
J'aimerais savoir si vous pouvez utiliser cette approche pour s'assurer qu'un type=nombre d'entrée est un clavier numérique. Aussi loin que je reçois, InputMethodManager ne peut ouvrir le standard de clavier (Azerty) car il ne sait pas quel élément HTML a actuellement le focus. À l'aide de wv.requestFocus n'a pas aidé.

OriginalL'auteur Swaroop | 2011-04-14