株式会社スタジオザンビ

スマホメニュー

ホームページ制作・ウェブアプリ制作 株式会社STUDIOザンビ 帯広/十勝/北海道

ホームページ作成・webシステム開発からデジタルコンテンツまで、付加価値の高いデザインやWEBシステムをご提供いたします。

BLOGブログ. 業務日誌

androidアプリで回転後のViewサイズを取得する

androidアプリで回転後のViewサイズを取得する

Google先生に尋ねてもピッタリの方法が見つからなかったのだが、皆さんどうしてるんだろう?AsyncTask使ってなんとかなったのだが、正しい方法知ってる方教えていただけませんか。

参考にさせていただいた
http://techbooster.org/android/hacks/16066/
で「コンテンツ領域」と書かれてるアイツです。

activity_main使わないで、コード内でガツガツViewをレイアウトしたい派は回転時のレイアウトもonDestroyしないで自分で再配置したい派…だと思うのですが違いますか違いますね。

回転時View再描画処理をonConfigurationChangedで行うが、この時コンテンツ領域は回転前のViewサイズしか取得できないので細かいレイアウト調整に困る。


API 15: Android 4.0.3 (IceCreamSandwich)

android:configChanges="orientation|screenSize"
↑AndroidManifest.xmlのactivityに追加


■回転時にViewのサイズが取得できないテスト

まずうまくいかなかった例。
 

public class RoteSizeTest01 extends Activity {
    Activity app=this;
    AbsoluteLayout appbase; //AbsoluteLayout大好き
    TextView textview=null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //サイズを調べるベースview(青)設置
        appbase=new AbsoluteLayout(app);
        appbase.setBackgroundColor(Color.parseColor("#ff0000ff"));
        app.setContentView(appbase);

        //ここだとviewのサイズが取得できない却下
        //makeView();
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);

        //viewのサイズ正しく取得できるonWindowFocusChangedだけどイヤだ
        if(textview==null){
            makeView();
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig){
        super.onConfigurationChanged(newConfig);

        //回転時再描画
        //ウインドウサイズは正しいけどviewのサイズは正しくない?
        makeView();
    }

    //view作成
    public void makeView(){
        //textview削除
        if(textview!=null){
            appbase.removeView(textview);
            textview=null;
        }

        //ウインドウサイズ
        WindowManager windowmanager=getWindowManager();
        Point point=new Point();
        windowmanager.getDefaultDisplay().getSize(point);
        int window_w=point.x;
        int window_h=point.y;

        //view(青)サイズ取得
        int view_w=appbase.getWidth();
        int view_h=appbase.getHeight();

        //textview構築
        int textview_w=view_w-200;
        int textview_h=view_h-200;
        int textview_x=100;
        int textview_y=100;
        textview=new TextView(app);
        textview.setTextColor(Color.parseColor("#ff000000"));
        textview.setBackgroundColor(Color.parseColor("#ffffff00"));
        appbase.addView(textview, new AbsoluteLayout.LayoutParams(textview_w,textview_h,textview_x,textview_y));

        textview.setText(
            "Viewサイズ取得おかしいテスト\n\n"+
            "画面サイズ\n"+
            "width:"+window_w+" height:"+window_h+"\n\n" +
            "ベースView(青)サイズ\n"+
            "width:"+view_w+" height:"+view_h
        );
    }
}

最初のView描画は正しいが、回転時にレイアウトが崩れる。
回転しても画面サイズは正しく取得できるが、青いベースViewが回転前のサイズしか取得できない。
※どこかの設定でできるなら教えてください。

androidアプリで回転後のViewサイズを取得する

■AsyncTaskにまかせてみるテスト

json読む処理してたAsyncTaskでの描画が正しく動いてたので試してみるテスト。
 

public class RoteSizeTest02 extends Activity {
    Activity app=this;
    AbsoluteLayout appbase; //AbsoluteLayout大好き
    TextView textview=null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //サイズを調べるベースview(青)設置
        appbase=new AbsoluteLayout(app);
        appbase.setBackgroundColor(Color.parseColor("#ff0000ff"));
        app.setContentView(appbase);

        //AsyncTaskに託す
        resetGetViewSize();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig){
        super.onConfigurationChanged(newConfig);

        //回転時再描画、AsyncTaskに託す
        resetGetViewSize();
    }

    //AsyncTask作成
    public void resetGetViewSize(){
        //回転時の動作が怪しくて処理が重いと出ないかも
        Toast.makeText(app,"View構築中 ...", Toast.LENGTH_SHORT).show();

        //AsyncTask完了時にView作成
        GetViewSize getviewsize=new GetViewSize(new GetViewSize.GetViewSizeCallback(){
            public void PostExecute(boolean res){
                makeView();
            }
        });
        getviewsize.execute(new Object[]{});
    }

    //view作成
    public void makeView(){
        //textview削除
        if(textview!=null){
            appbase.removeView(textview);
            textview=null;
        }

        //ウインドウサイズ
        WindowManager windowmanager=getWindowManager();
        Point point=new Point();
        windowmanager.getDefaultDisplay().getSize(point);
        int window_w=point.x;
        int window_h=point.y;

        //view(青)サイズ取得
        int view_w=appbase.getWidth();
        int view_h=appbase.getHeight();

        //textview構築
        int textview_w=view_w-200;
        int textview_h=view_h-200;
        int textview_x=100;
        int textview_y=100;
        textview=new TextView(app);
        textview.setTextColor(Color.parseColor("#ff000000"));
        textview.setBackgroundColor(Color.parseColor("#ff00ff00"));
        appbase.addView(textview, new AbsoluteLayout.LayoutParams(textview_w,textview_h,textview_x,textview_y));

        textview.setText(
            "Viewサイズ取得できた?\n\n"+
            "画面サイズ\n"+
            "width:"+window_w+" height:"+window_h+"\n\n" +
            "ベースView(青)サイズ\n"+
            "width:"+view_w+" height:"+view_h
        );
    }
}

Viewを描画したいタイミングでAsyncTaskのGetViewSizeに投げる。
↓GetViewSize側ではsleepして親に処理を返すだけ。
 
public class GetViewSize extends AsyncTask<Object,Integer,Boolean> {

    private GetViewSizeCallback callback=null;
    public interface GetViewSizeCallback{
        void PostExecute(boolean res);
    }

    public GetViewSize(GetViewSizeCallback callback){
        this.callback=callback;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
    }

    @Override
    protected Boolean doInBackground(Object... params) {
        //好きなだけ待つ
        try {
            Thread.sleep(1500);
            return true;
        } catch (InterruptedException e) {
            return false;
        }
    }

    @Override
    protected void onPostExecute(Boolean res) {
        callback.PostExecute(res);
    }
}

doInBackgroundでsleep、Viewの描画は親の方がやりやすそうなので完了時のonPostExecuteで親に返す。
回転時に処理がsleepするのでToastしているが実際アプリに組み込んだ際は、処理が重いせいか不安定で出ない場合があった。

androidアプリで回転後のViewサイズを取得する

以上、もしお役に立った場合は心の中で「いいね」と呟いてください。
AbsoluteLayout大好き。

  • ヒトコトどうぞ

    ※500文字以内

    ※スマートフォンなど画像認証がうまくいかない場合は、一度[変更]してからご入力ください。

    CAPTCHA Image

    英数字5桁(変更

    ありがとうございます!↓やってみます、もし思い通りの動きができましたらまたブログに書かせていただきます。

    1.android.view.Viewを継承しているクラスを作り、getViewTreeObserver()を呼ぶ
    2.ViewTreeObserverクラスのaddOnGlobalLayoutListenerを使ってViewTreeObserver.OnGlobalLayoutListenerを実装したクラスを追加
    3.描画が終了後ViewTreeObserver.OnGlobalLayoutListenerを実装クラスのonGlobalLayout()が呼び出される
    4.onGlobalLayout()の中で、view.getWidth()やview.getHeight()を使って値を取得する
    ※OnGlobalLayoutListenerの使用が終了したらremoveOnGlobalLayoutListenerでリセットしておくと良い、無駄に呼び出されるおそれがなくなります

    なんだかよくわからないけどわかった!