2012-02-16 12 views
14

Ponieważ sposób wywołania javascript w WebView odbywa się przez loadUrl ("javascript: ..."); Klawiatura nie może pozostać otwarta.WebView ukrywa klawiaturę podczas loadUrl(), co oznacza, że ​​klawiatura nie może pozostać otwarta podczas wywoływania javascript

Sposób loadUrl() wzywa loadUrlImpl(), który wywołuje metodę o nazwie clearHelpers() które następnie wywołuje clearTextEntry(), które następnie wywołuje hideSoftKeyboard() a następnie stajemy oh tak samotny jak klawiatura odchodzi.

O ile widzę, wszystkie są prywatne i nie można ich przesłonić.

Czy ktoś znalazł obejście tego problemu? Czy istnieje sposób na wymuszenie otwarcia klawiatury lub wywołanie javascript bezpośrednio, bez przechodzenia przez loadUrl()?

Czy mimo to należy zastąpić WebView w taki sposób, aby uniemożliwić wywołanie metody clearTextEntry() prywatnej?

+0

spróbuj wywołać to po załadowaniuUrl(); ((InputMethodManager) getSystemService (Context.INPUT_METHOD_SERVICE)). ToggleSoftInput (InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY); – zeitue

+0

Hmmmm, tak blisko. Klawiatura zamyka się, a następnie ponownie otwiera się bardzo szybko. Wygląda dość dziwnie;). Chociaż mogę eksperymentować z tym pomysłem więcej. – cottonBallPaws

+0

Inną częścią problemu jest to, że clearTextEntry() usuwa także EditText, na którym koncentruje się klawiatura. – cottonBallPaws

Odpowiedz

12

Aktualizacja

KitKat dodaje metodę publiczną za wywoływanie JavaScript bezpośrednio: evaluateJavascript()

Dla starszych interfejsów API, można spróbować rozwiązania jak poniżej, ale gdybym miał to zrobić jeszcze raz będę wyglądać na samym budowaniu metody kompatybilności, która w KitKat używa powyższej metody i na starszych urządzeniach, używa refleksji, aby przejść do wewnętrznej, prywatnej metody: BrowserFrame.stringByEvaluatingJavaScriptFromString()

Następnie można nazwać javascript bezpośrednio, bez konieczności radzenia sobie z lo adUrl i dodanie do skryptu "javascript: ".

Old Odpowiedź

Zgodnie z wnioskiem ALOK Kulkarni, dam szorstka przegląd ewentualnego obejścia myślałem od tego. Nie próbowałem tego, ale teoretycznie powinno działać. Ten kod będzie surowy i ma jedynie służyć jako przykład.

Zamiast wysyłać wywołania przez loadUrl(), kolejkujesz wywołania javascript, a następnie javascript usuwa je. Niektóre rzeczy takie jak:

private final Object LOCK = new Object(); 
private StringBuilder mPendingJS; 

public void execJS(String js) { 
    synchronized(LOCK) { 
     if (mPendingJS == null) { 
      mPendingJS = new StringBuilder(); 
      mPendingJS.append("javascript: "); 
     } 
     mPendingJS 
      .append(js) 
      .append("; "); 
    } 
} 

Zamiast wywoływać metodę loadUrl() wywołaj tę metodę. (Dla uproszczenia użyłem zsynchronizowanego bloku, ale może to być lepiej dostosowane do innej trasy, ponieważ javascript działa na własnym wątku, to będzie wymagało w ten czy inny sposób zabezpieczenia wątku).

Wtedy twój WebView musiałby interfejs tak:

public class JSInterface { 

    public String getPendingJS() { 
     synchronized(LOCK) { 
      String pendingCommands = mPendingJS.toString(); 
      mPendingJS.setLength(0); 
      mPendingJS.append("javascript: "); 
      return pendingCommands; 
     } 
    } 

} 

która zwraca ciąg z toczącym poleceń i je tak, aby nie dostać zwracany znowu czyści.

by dodać go do WebView tak:

mWebView.addJavascriptInterface(new JSInterface(), "JSInterface");

Następnie w javascript by ustawić jakiś przedział, w którym należy opróżnić oczekujących poleceń. W każdym interwale wywołałby on JSInterface.getPendingJS(), który zwróciłby ciąg wszystkich oczekujących poleceń, a następnie mógłbyś je wykonać.

Można to poprawić poprzez dodanie metody execJS, aby sprawdzić, czy pole EditText istnieje w WebView i jest aktywne. Jeśli takowy istnieje, to użyłbyś tej metody kolejkowania, ale jeśli nie było w niej fokusa, możesz po prostu wywołać metodę loadUrl() jak normalnie. W ten sposób wykorzystuje to obejście tylko wtedy, gdy faktycznie jest to konieczne.

+0

Dzięki za urywek, naprawdę doceniamy twój wysiłek. Sprawdziłem wywołanie metody interfejsu JavaScript z Js na 2.3 i jej łamanie na pewno. Obawiam się, że to może nie działać w wersji 2.3. Ale sprawdzę na innych platformach 2.x, czy działa, czy nie. Dzięki. –

+1

Nie będzie działać w przypadku aplikacji sterowanych zdarzeniami. Pomyśl o aplikacjach na czat/SMS/telefonię. Podczas pisania warstwa Javy musi powiadomić interfejs użytkownika o zdarzeniu.Nie możesz po prostu wyciągnąć go z JavaScriptu zawsze. – Nizzy

+0

Próbowałem zaimplementować twoją metodę za pomocą ** funkcji Eval (jsString) ** w js. Ale powoduje to, że fokus traci swój pomysł? – DroidBot

0

Jeśli chodzi o starsze interfejsy API (pre 19), użyłem metody podobnej do odpowiedzi wyjątkowej, ale nieco innej.

pierwsze, śledzić, czy klawiatura jest wyświetlana za pomocą JavaScript w WebView z grubsza tak:

document.addEventListener("focus", function(e){   
    var el = e.target; 
    reportKeyboardDisplayedToJava(isInputElement(el)); 
}, true); 

document.addEventListener("blur", function(e){   
    reportKeyboardDisplayedToJava(false); 
}, true); 

Jeśli zostanie wyświetlona klawiatura, a wtrysk js próby przez warstwę Android Java - "Odroczam" ten zastrzyk. Dodaję go do listy ciągów, pozwalam użytkownikowi na dokończenie wprowadzania, a następnie po zniknięciu klawiatury wykrywam i wykonuję zaległe zastrzyki.

Powiązane problemy