Sencha Touch + PhoneGapでAndroid2.1でのフォームがずれる/残るバグの対処法
Sencha TouchとPhone Gapを使って、ハイブリッドアプリを作っているときに、
Android2.1, 2.1updateでフォームがおかしくなる現象に遭遇しました。
OS:
Android 2.1
JS:
Sencha Touch 1.1
現象には以下のようないくつかの種類があります。
画面遷移後もフォームが画面の上に残る
フォーカスしたあとにスクロールするとフォームがずれる
これらの根本的な原因はAndroidがフィールドの入力の際にinputフィールドとは別に入力フィールドが画面の上に表示して入力を実装していることのようです。
Android端末では、WebView上のテキストフィールドやパスワードフィールドは、ネイティブ側で上書きされているタメです。
Android 2.1系ではこのWebTextViewが良くない動きをしているようです。
そのため、テキストフィールドやパスワードフィールドが残ってしまう等現象が発生します。
これはPhoneGapを使っていなくてもブラウザであっても同じ不具合が発生します。
Sencha Touch の Kitchen Sink Demoでも再現します。
→ http://dev.sencha.com/deploy/touch/examples/kitchensink/
これれSench のForumにも上がっているようですが、OPENのままなです。
→ http://www.sencha.com/forum/showthread.php?118678-OPEN-660-Android-Password-Field-superfocus-persistance&p=579440&viewfull=1&langid=14
PhoneGap単体でも起こるらしいです。
→ http://stackoverflow.com/questions/5681013/input-has-different-style-on-focus
この問題を回避するにはJavaScript単体で回避することは不可能で、Androidのネイティブコードから処理を行う必要があります。
ちなみに、上書きを行っているクラスは、WebTextViewクラスで行われています。
→ http://www.androidjavadoc.com/2.3/android/webkit/WebTextView.html
また、上書きを行った際は、WebView のChildView として実行されるので、
WebViewクラスのremoveAllViewsInLayoutメソッドを使用して、
ChildViewをクリアすることで、本現象を解消することができます。
PanelがActiveになったタイミングや、スクロール開始時、フォーカスがあたったタイミング、フォーカスが外れたタイミングで、
以下のJavaScript コードを実行することで、ChildViewをクリアすることが可能です。
//PhoneGapを利用する //ネイティブ側でこのメソッドを実装しておき、Phonegapを経由してコールする。 mywebview.removeAllViewsInLayout();
以下は、サンプルのJavaコードです。
=== MAIN CLASS ===
public class App extends DroidGap {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.init();
final MyWebView myWebView = new MyWebView(appView, this);
appView.addJavascriptInterface(myWebView, "mywebview");
super.loadUrl("file:///android_asset/www/index.html");
}
}
=== MAIN CLASS ===
=== MyWebView CLASS ===
public class MyWebView extends Activity {
public WebView webView;
public DroidGap droidGap;
public MyWebView(WebView webView, DroidGap droidGap) {
this.webView = webView;
this.droidGap = droidGap;
}
/**
* Remove All ChildView on WebView
*
*/
public synchronized void removeAllViewsInLayout() {
try {
Runnable runnable = new Runnable() {
public void run() {
webView.removeAllViewsInLayout();
};
};
droidGap.runOnUiThread(runnable);
} catch (Exception e) {
e.printStackTrace();
}
}
}
=== MyWebView CLASS ===
上のようにJava側でメソッド(webView.removeAllViewsInLayoutメソッド)を作成して、JavaScriptからはPhoneGap経由でネイティブのメソッドをコールすることで、ChildViewをクリアして、HTMLの上に表示される別の入力フィールドを取り除きます。
残念ながら必ずネイティブのコードを利用しないといけないので、JSだけで解決できませんがPhoneGap等を使いネイティブにラップしてる場合はこのやり方が使えそうです。
本当は、なんとかJSだけで解決したいですね



