1. 程式人生 > >android在程式碼中獲取view寬/高為0解決方法

android在程式碼中獲取view寬/高為0解決方法

在專案中,我們要在程式碼中獲取view的寬高資訊,有可能就會在onCreat或者onResume方法中去獲取,原因就是view的measure過程與Activity的生命週期不是同步執行的,因此無法保證在onCreat,onResume,onStart時這個view是否已經測量完畢,如果沒有測量完畢,得到的結果就是0。這裡給出4種解決辦法

  • (1) onWindowFocusChanged
    onWindowFocusChanged含義就是view已經初始化完畢,這個時候去獲取寬高就沒問題了,但是要注意的是此方法會被呼叫很多次,當Activity的視窗失去或者得到焦點都會呼叫一次,也就是Activity onResume或onPause時都會呼叫。典型程式碼如下:
@Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus){
            int width = view.getMeasuredWidth();
            int height = view.getMeasuredHeight();
        }
    }
  • (2) view.post(runnable)
    通過post將一個runnable投遞到訊息佇列的尾部,然後等Looper呼叫此runnable的時候,view也就已經初始化好了,典型程式碼如下:
@Override
    public void onStart() {
        super.onStart();
        view.post(new Runnable){
@Override
public void run(){
        int width = view.getMeasuredWidth();
        int height = view.getMeasuredHeight();
        }
    } 
}
  • (3) viewTreeObserver
    使用viewTreeObserver的眾多回調可以完成這個功能,比如使用OnGlobalLayoutListener這個介面,當view樹的狀態發生改變或者view樹的內部view的可見性發生改變時,onGlobalLayout方法會被呼叫,因此這是獲取view寬高很好的時機。需要注意的是,伴隨著view樹狀態改變onGlobalLayout會被呼叫很多次,典型程式碼如下:
@Override
    protected void onStart() {
        super.onStart();
        ViewTreeObserver observer = view.getViewTreeObserver();
        observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
               int width = view.getMeasuredWidth();
        int height = view.getMeasuredHeight(); 
            }
        });
    }
  • (4) view.measure(intwidthMeasureSpec,intheightMeasureSpec)
    通過手動對view的measure來得到view的寬高,這種方法比較複雜,要分情況處理,根據view的LayoutParams來分:
  • math_parent
    無法測量,因為構造此種MeasureSpec需要知道parentSize,即父容器的剩餘空間,而此時我們無法知道parentSize的大小,所以理論上測量不出view的大小。
  • 具體數值(dp/px)
    比如說寬高都是100px,如下:
int  widthMeasureSpec=MeasureSpec.makeMeasureSpec(100,MeasureSpec.EXACTLY);
int  heightMeasureSpec=MeasureSpec.makeMeasureSpec(100,MeasureSpec.EXACTLY);
view.measure(widthMeasureSpec,heightMeasureSpec);
  • wrap_content
int  widthMeasureSpec=MeasureSpec.makeMeasureSpec((1<<30)-1,MeasureSpec.AT_MOST);
int  heightMeasureSpec=MeasureSpec.makeMeasureSpec((1<<30)-1,MeasureSpec.AT_MOST);
view.measure(widthMeasureSpec,heightMeasureSpec);