I have an application with just a visible WebView
component to it which is used to display some dynamically generated HTML (can run Javascript too). It’s enabled for the WebView
.
For a few pages I am trying to set the focus of one of the input text boxes after the page load has finished – not through Body onLoad()
, but instead by a JS call after the page has finished loading i.e. in onPageFinished()
. Most of the javascript executes fine
webview.loadURL("javascript:JSMethod();");
But when I use the same call to do a document.getElementById('text1').focus()
– the cursor does reach the element but the Soft Keyboard
won’t pop out. The same javascript code when executed from a button on the page does have the desired effect.
I am attaching the source code which has 3 buttons
Focus Text1
– Put the cursor on the text1 and pops up the Softkeyboard.Java Focus Text1
– Calls Java to execute the same JS. Only shows the cursor there and doesn’t pop out the keyboardJava Focus Text1 And Keyboard Open
– Calls JS from Java and Forces Keyboard open.
My understanding is that the JS execution should work the same whether executed from the browser using a button/event or as sent from Java through WebView.loadURL()
.
Here’s my Queries
- Am I missing something when using
Button#2
? That’s how my current code is and I only see the cursor is set but the SoftKeyboard won’t open. - When I use logic as written in
Button#3
, I some times don’t see the cursor on the field but gives me the desired effect and the cursor becomes visible when I type something in the popped up keyboard. - Could the behavior I see in
Button#2
be a bug in Android JS execution? Or could it be that theWebView
doesn’t have focus that’s why only the cursor is displayed? I also triedwebview.requestFocus()
– I can’t writerequestFocusOnTouch()
as it’s the only View I have and am expecting it’s focused automatically.
The Java code which demos the behavior is
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 Update 24-06-2011
To make this work, you need to use wv.requestFocus(View.FOCUS_DOWN)
just before the actual JS focus call. I modified the javaFocus()
method above to the correct version below. Earlier when I mentioned that I was using requestFocus(), I was using that when the WebView
was initialized in the method onCreate()
. The primary difference is now we’re forcing the WebView
to get focus each time just before the Javascript document.getElementById("text1").focus();
is executed.
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); }
Also to ensure that this issue wasn’t fixed because of focus triggered through touch etc, I am using a background thread to initiate the javaFocus() after 5 seconds of WebView Displayed. The modified onCreate()
is below.
..... 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....
Advertisement
Answer
It could be that the webview doesn’t have the application focus. Try executing;
wv.requestFocus(View.FOCUS_DOWN);