ExtJSで楽しくRIA業務アプリ開発

株式会社sus4 開発チーム

Sencha Touch + PhoneGapでAndroid2.1でのフォームがずれる/残るバグの対処法

コメントはありません

このエントリーを含むはてなブックマークはてなブックマーク - Sencha Touch + PhoneGapでAndroid2.1でのフォームがずれる/残るバグの対処法 この記事をクリップ!Livedoorクリップ - Sencha Touch + PhoneGapでAndroid2.1でのフォームがずれる/残るバグの対処法 Yahoo!ブックマークに登録 BuzzurlにブックマークBuzzurlにブックマーク このエントリをつぶやくこのWebページのtweets Share on Tumblr FC2ブックマークへ追加 newsing it! この記事をChoix! Googleブックマークに追加 Bookmark this on Delicious Digg This

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だけで解決したいですね

  • Share/Bookmark


佐竹 裕行

1982年生まれ。滋賀→はこだて→名古屋→大垣→名古屋。
2006年名古屋学芸大学映像メディア学科卒、その後IAMAS卒(Studio2、6期生)。2009年にsus4に入社。学生時代はMax/MSP JitterやGainerばっかり使っていたが、現在社内では主にExtとモバイル開発、動画サービスのバックエンドを担当。知る人ぞ知るアノ鍵の人。

Written by 佐竹 裕行

6 月 1st, 2011 at 6:31 pm

Posted in Sencha Touch

Tagged with , , , , ,

コメントを残す

Get Adobe Flash playerPlugin by wpburn.com wordpress themes