原因
無法在Activity的onCreate或者onResume方法中正確的到某個View的寬/高信息,因為View的measure過程和Activity的生命周期方法不是同步執行的,因此無法保證Acitivity執行了onCreate、onStart、onResume時某個View已經測量好了,如果沒有測量好,那么獲得的寬/高就是0。
解決方法
1、Activity/View.onWindowFocusChanged
onWindowFocusChanged方法:View已經初始化完畢,寬/高已經準備好了,這個時候獲取寬高是沒問題的。
當Acitivity的窗口得到焦點或者失去焦點時均會被調用一次。
public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChagned(hasFocus); if(hasFocus){ int width = view.getMeasuredWidth(); int height = view.getMeasuredHeight(); } }
2、view.post(runnable)
通過post可以將一個runnable投遞到消息隊列的尾部,然后等待Looper調用此runnable的時候,View也已經初始化好了。
protected 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的寬高。
protected void onStart() { super.onStart(); ViewTreeObserver observer = view.getViewTreeObserver(); observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @SuppressWarnings("deprecation") @Override public void onGlobalLayout() { view.getViewTreeObserver().removeGlobalOnLayoutListener(this); int width = view.getMeasuredWidth(); int height = view.getMeasuredHeight(); } });}
手動重寫view.measure方法獲得寬高