Androidでの測定コントロールの幅と高さ

6621 ワード

前言:Androidの開発では、コントロールの幅と高さを測定する必要がある場合があり、getHeight()、getWidth()、getMeasureHeight()、getMeasureWidth()メソッドを直接呼び出す必要があり、得られる値はすべて0であり、これは実際にviewの描画プロセスにかかわる.
View描画プロセス:(簡単な分析)measure(システム測定コントロールの幅と高さを強制する)->layout(コントロールの親レイアウトにおける位置を決定する)->draw(描画view)で、drawメソッドはonCreate()メソッドの実行が終了する後に呼び出される.
実装方法:
一、Viewを使う.Measure測定View:この方法で測定した幅と高さは、ビューの描画が完了した後の実際の幅と高さと一致しない可能性があります.
int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
view.measure(w, h);
view.getMeasuredWidth(); //     
view.getMeasuredHeight(); //     

二、ViewTreeObserverを使用する.OnPreDrawListenerリスニングイベント:ビューが描画されるときにリスニングイベントが呼び出され、複数回呼び出されるため、ビューの幅と高さを取得した後にリスニングイベントを削除します.
view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {

    @Override
    public boolean onPreDraw() {
    //    
        view.getViewTreeObserver().removeOnPreDrawListener(this);
        view.getWidth(); //     
        view.getHeight(); //     
        return true;
    }
});

三、ViewTreeObserverを使用する.OnGlobalLayoutListenerリスニングイベント:レイアウトが変更されたり、ビューのビジュアル状態が変更されたりしたときに呼び出されるイベントは、複数回呼び出されるため、ビューの幅と高さを取得した後にremoveメソッドを実行してリスニングイベントを削除する必要があります.
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

        @Override
        public void onGlobalLayout() {
            //          16
            if (Build.VERSION.SDK_INT >= 16) {
                                                 view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
            else {
                view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
            view.getWidth(); //     
            view.getHeight(); //     
        }
    });
}

四、Viewを書き換えるonSizeChangedメソッド:ビューのサイズが変更されたときに呼び出されるメソッドは、複数回呼び出されるため、幅と高さを取得した後、コードを無効にすることを考慮する必要があります.このインプリメンテーションメソッドは、Viewを継承し、複数回呼び出される必要があり、使用は推奨されません.
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    view.getWidth(); //     
    view.getHeight(); //     
}

五、ViewのonLayoutメソッドを書き換える:このメソッドは複数回呼び出され、幅と高さを取得した後、コードを無効にすることを考慮する必要があります.このインプリメンテーションメソッドは、Viewを継承し、複数回呼び出される必要があり、使用は推奨されません.
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    super.onLayout(changed, l, t, r, b);
    view.getWidth(); //     
    view.getHeight(); //     
}

六、Viewを使う.OnLayoutChangeListenerリスニングイベント(API>=11):ビューのlayoutが変更されたときにイベントが呼び出され、複数回呼び出されるため、ビューの幅と高さを取得した後にremoveメソッドを実行してリスニングイベントを削除する必要がある.
view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { 
    @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
    //    
    view.removeOnLayoutChangeListener(this); 
    view.getWidth(); //      
    view.getHeight(); //      
    } 
});

七、Viewを使う.Post()メソッド:Runnableオブジェクトのメソッドは、Viewのmeasure、layoutなどのイベントが完了した後にトリガーされます.UIイベントキューはイベントを順番に処理し、setContentView()が呼び出されると、イベントキューには再layoutを要求するメッセージが含まれます.したがって、キューにpostされたRunnableオブジェクトは、Layoutが変化した後に実行されます.この方法は一度しか実行されず、論理が簡単で、使用を推奨します.
view.post(new Runnable() {
 @Override
    public void run() {
        view.getWidth(); //     
        view.getHeight(); //     
    }
});