實際上在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開發藝術探索》