天天看點

Android中擷取View的寬/高的時機

實際上在onCreate、onStart、onResume中均無法正确得到某個View的寬/高資訊,這是因為View的measure過程和Activity的生命周期方法不是同步執行的。如果View還沒測量完畢,那麼獲得寬/高就是0。下面列出獲得View寬/高的機時:

Activity/View#onWindowFocusChanged

onWindowFocusChanged這個方法的含義是:View已經初始化完畢了,寬/高已經準備好。需注意的是,它會被調用多次,當Actitvity的視窗得到焦點和失去焦點時均會被調用一次。具體來說,當Activity繼續執行和暫停執行時均會調用,如果頻繁地進行onResume和onPause,那麼它也會被頻繁調用。典型代碼如下:

@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
    super.onWindowFocusChanged(hasWindowFocus);
    if (hasWindowFocus) {
        int width = view.getMeasuredWidth();
        int height = view.getMeasuredHeight();
    }
}
           

view.post(rennable)

通過post可以将一個runnable投遞到消息隊列的尾部,然後等待Looper調用此runnable的時候,View也已經初始化好了。典型代碼如下:

@Override
protected void onStart() {
    super.onStart();
    view.post(new Runnable() {
        @Override
        public void run() {
            int width = view.getMeasuredWidth();
            int height = view.getMeasuredHeight();
        }
    });
}
           

ViewTreeObserver

使用ViewTreeObserver的從多回調可以完成這個功能,比如OnGlobalLayoutListener這個接口,當View樹的狀态發生改變或者View樹内部的View的可見性發生改變時,onGlobalLayout方法将被回調。需要注意的是,伴随着View樹的狀态改變等,onGlobalLayout會被調用多次。典型代碼如下:

@Override
protected void onStart() {
    super.onStart();

    ViewTreeObserver observer = view.getViewTreeObserver();
    observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @SuppressWarnings("deprecation")
        @Override
        public void onGlobalLayout() {
            view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            int width = view.getMeasuredWidth();
            int height = view.getMeasuredHeight();
        }
    });
}
           

 ——本博文部分内容參考自《Android開發藝術探索》