Android WebView – Nastavení zaměření pole HTML pomocí Javascriptu

Mám aplikaci pouze s viditelným WebView komponentu, která slouží k zobrazení nějakého dynamicky generovaného HTML (lze spustit i Javascript). Je povoleno pro WebView .

U několika stránek se pokouším nastavit fokus jednoho ze vstupních textových polí po dokončení načítání stránky – ne skrz Text onLoad() , ale místo toho voláním JS po dokončení načítání stránky, tj. v onPageFinished() . Většina javascriptu se spouští dobře

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

Ale když používám stejné volání k provedení document.getElementById('text1').focus() – kurzor dosáhne prvku, ale Soft Keyboard nevyskočí. Stejný kód javascriptu při spuštění z tlačítka na stránce má požadovaný účinek.

Přikládám zdrojový kód, který má 3 tlačítka

  1. Focus Text1 – Umístěte kurzor na text1 a zobrazí se softwarová klávesnice.
  2. Java Focus Text1 – Volá Javu, aby provedla stejný JS. Zobrazí pouze kurzor a nevysune klávesnici
  3. Java Focus Text1 And Keyboard Open – Volá JS z Java a vynutí otevření klávesnice.

Chápu to tak, že spuštění JS by mělo fungovat stejně, ať už je spuštěno z prohlížeče pomocí tlačítka/události, nebo jako odeslané z Javy přes WebView.loadURL() .

Zde jsou mé Dotazy

  1. Při použití Button#2 mi něco chybí ? Takto je můj aktuální kód a vidím, že je nastaven pouze kurzor, ale softwarová klávesnice se neotevře.
  2. Když používám logiku napsanou v Button#3 , Někdy nevidím kurzor na poli, ale dává mi požadovaný efekt a kurzor se zviditelní, když něco napíšu na vyskakovací klávesnici.
  3. Mohlo by chování, které vidím v Button#2 je chyba v provádění Android JS? Nebo by to mohlo být, že WebView nemá fokus, proto je zobrazen pouze kurzor? Zkoušel jsem také webview.requestFocus() – Nemohu napsat requestFocusOnTouch() protože je to jediný pohled, který mám, a očekávám, že se automaticky zaostří.

Kód Java, který ukazuje chování, je

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

Aktualizace řešení 24. 6. 2011 Aby to fungovalo, musíte použít wv.requestFocus(View.FOCUS_DOWN) těsně před skutečným voláním JS focus. Upravil jsem javaFocus() metoda výše na správnou verzi níže. Dříve, když jsem zmínil, že používám requestFocus(), používal jsem to, když WebView byl inicializován metodou onCreate() . Hlavním rozdílem je, že nyní vnucujeme WebView abyste se zaměřili pokaždé těsně před Javascript document.getElementById("text1").focus(); je proveden.

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

Abych se také ujistil, že tento problém nebyl vyřešen kvůli zaměření spouštěnému dotykem atd., používám vlákno na pozadí ke spuštění javaFocus() po 5 sekundách zobrazení WebView. Upravený onCreate() je níže.

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

Odpověď

Je možné, že webové zobrazení nemá zaměření aplikace. Zkuste spustit;

wv.requestFocus(View.FOCUS_DOWN);