很多初學者都會犯一個錯誤 ,就是在onCreate或者onStart裡面去獲取view的大小,然而這樣獲取到的寬高通常都是0,為什麼呢?因為view的測量過程和activity的生命周期不是同步的,因此無法保證執行了onCreate、onStart、onResume的時候view已經測量完畢。如果還 ...
很多初學者都會犯一個錯誤 ,就是在onCreate或者onStart裡面去獲取view的大小,然而這樣獲取到的寬高通常都是0,為什麼呢?因為view的測量過程和activity的生命周期不是同步的,因此無法保證執行了onCreate、onStart、onResume的時候view已經測量完畢。如果還沒測量完,那麼獲取到的寬高就會是0。
那麼我們應該在哪裡獲取view的大小呢?以下有幾種辦法:
1、在onWindowFocusChanged裡面獲取。
這個方法是當Activity的視窗失去焦點或者獲取焦點的時候就會調用,比如進行onResume或者onPause的時候,它就會被調用(因此它有可能被多次調用)。我們可以用下麵的模板來獲取view的寬高。
public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if(hasFocus) { int width=view.getMeasuredWidth(); int height=view.getMeasuredHeight(); } }
2、使用view.post(runnable).
通過這個方法可以把一個runnable任務投遞到消息隊列的尾部。在該方法裡面,會先獲取view所線上程的handler(view所在的線程當然就是UI線程),然後將任務投遞到handler所對應的消息隊列的尾部,等待looper去獲取,當looper獲取到的時候,view已經初始化完畢,所以就能正確的獲取它的寬高了。代碼模板如下:
protected void onStart() { super.onStart(); view.post(new Runnable(){ @Override public void run() { int width=view.getMeasuredWidth(); int height=view.getMeasuredHeight(); } }); }
3、使用ViewTreeObserver
ViewTreeObserve有許多回調介面,比如OnGlobalLayoutListener這個介面,當view樹的狀態發生改變的時候,或者view樹內部view的可見性發生改變的時候,該介面裡面的onGlobalLayout方法將被回調,可以在這個時候獲取view的寬高。因此該方法可能會被多次調用,我們應當在獲取到view的寬高之後把該介面監聽移除。代碼模板如下:
@Override protected void onStart() { super.onStart(); ViewTreeObserver observer=view.getViewTreeObserver(); observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { view.getViewTreeObserver().removeOnGlobalLayoutListener(this); int width=view.getMeasuredWidth(); int height=view.getMeasuredHeight(); } }); }
以上便是獲取view大小的三種常用的方法。