2011年11月20日日曜日

起動直後にViewのサイズを動的に変更する

起動直後にViewのサイズを動的に変更する

アプリが立ち上がってしまった後でViewのサイズを取得・変更することは比較的簡単にできるかもしれません。
しかし、困難なのは、起動直後に、動的に変更した後の画面を、一番最初に利用者に見せることです。

この記事は、様々なViewの縦幅を揃えるの続編です。幅を静的に整えるのであればxmlでダミーを挿入すれば良いのです。
しかし、本番用のアプリに、ダミーを挿入したままだと、関係者に説明が付きません。黙っていれば、誰も気が付きませんが。

そこで、本番用のために、xmlだけで対応するのではなく、codeで、Viewの生成時における幅を取得することにします。

試行錯誤 その1
Activityが起動してくる途中で次のような様々なメソッドが実行されます。
  1. onCreate
  2. onStart
  3. onResume
  4. onPostResume
一番最後に実行されるのがonPostResumeです。残念なことに、この時点においても、xmlで定義したViewのサイズを取得することはできません。
onPostResumeの中で、Handler.post(Runnable)を実行させ、onPostResumeを抜け出た直後にViewのサイズの取得を試みましたが、できませんでした。
Handler.postDelayed(Runnable, 1000)を実行させたところ、抜け出た1秒後に取得ができました。
しかし、できるからといって、こんな方法はダメです。何故ならば、この場合は1秒後に取得できましたが、端末の状況によっては、もっと長い時間がかかることも想定しなければならないからです。実際には、そんなことは無いでしょうけど。

試行錯誤 その2
そこで、次の2点を満足させる方法を探し求めることになります。
  1. Viewをextendsしてcodingする。
  2. xmlで定義したViewをcodeでも取り扱えるようにする。
この仕掛けを講じるに際し、下記のサイトの記事を参考にしました。
Activity内でのViewの遷移について

この記事で注目すべきは、Activityと、extendsしたViewとの関連付けです。
xmlのrootの要素に、Package名を書いてあるのです。この方法により、関連付けができます。この方法は、結構重要だと思います。

この方法を使って、onPostResume内で、LayoutInflaterでinflateさせて、カスタムView内のonFinishInflateでサイズを取得するように試みましたが、できませんでした。残念です。

結論
Viewの幅と高さを取得する方法を考えるの投稿欄にコメントされているように、onWindowFocusChangedを使う方法しか無いようです。
まさか、こんな名前のメソッドで対応するとは、全く想像できませんでした。このため、遠回りな試行錯誤をしてしまいました。
参考:ビューのサイズを取得する

public class AdjustHeightActivity extends Activity{
    boolean IsStarted;
    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        IsStarted = false;
        setContentView(R.layout.main);
    }


    @Override
    public void onWindowFocusChanged(boolean hasFocus){
        super.onWindowFocusChanged(hasFocus);
        if(IsStarted==false){
            LinearLayout ll, llChild;
            View v;
            int i, iHeight, iChildren, iMaxHeight;
            
            iMaxHeight = 0;
            ll = (LinearLayout)findViewById(R.id.Main);
            iChildren = ll.getChildCount();
            for(i=0; i<iChildren; i++){
                llChild = (LinearLayout)ll.getChildAt(i);
                v = llChild.getChildAt(0);
                iHeight = v.getMeasuredHeight();
                if(iMaxHeight<iHeight) iMaxHeight = iHeight;
            }
            for(i=0; i<iChildren; i++){
                llChild = (LinearLayout)ll.getChildAt(i);
                v = llChild.getChildAt(0);
                iHeight = v.getHeight();
                iHeight = iMaxHeight - iHeight;
                iHeight /= 2;
                llChild.setPadding(0, iHeight, 0, iHeight);
            }
            IsStarted = true;
        }
    }
}

0 件のコメント:

コメントを投稿