原文地址:https://blog.csdn.net/chenbaige/article/details/77991594ide
可能不少狀況下,咱們都會有在activity中獲取view 的尺寸大小(寬度和高度)的需求。面對這種狀況,不少同窗立馬反應:這麼簡單的問題,還用你說?你是否是傻。。而後立馬寫下getWidth()、getHeight()等方法,洋洋得意的就走了。然而事實就是這樣的嗎?實踐證實,咱們這樣是獲取不到View的寬度和高度大小的,可能不少同窗又會納悶了,這是爲何呢?一直不都是這樣獲取大小的嘛!post
實際狀況下,View的measure過程和Activity的生命週期方法不是同步執行的,所以沒法保證Activity在執行完某個生命週期方法時View已經測量完畢了,這種狀況下,獲取到的尺寸大小就是0。所以,在不少狀況下,咱們正在爲咱們機智而得意時,事實卻讓咱們大跌眼鏡,甚是尷尬。this
接下來咱們介紹四種方式去正確的獲取View的尺寸大小。spa
onWindowFocusChanged方法執行時表明View已經初始化完畢了,寬度和高度已經測量完畢而且最終確認好了,這時咱們能夠放心的在這裏去獲取View 的寬度和高度。代碼以下:
.net
Activity的onWindowFocusChanged中獲取view的寬度和高度 @Override public void onWindowFocusChanged(boolean hasWindowFocus) { super.onWindowFocusChanged(hasWindowFocus); if(hasWindowFocus){ int width = view.getMeasuredWidth(); int height = view.getMeasuredHeight(); } }
注意:雖然使用很方便,但在使用這個方法時須要特別注意:onWindowFocusChanged會執行屢次,在Activity獲取焦點和失去焦點時都會被調用一次。即在onPause和onResume方法被執行時被反覆調用。code
經過View.post方法把Runnable對象放到消息隊列的末尾,當執行到這個runable方法的時候,View全部的初始化測量方法說明都已經執行完畢了。所以在這裏獲取的時候就是測量後的真實值。代碼以下:
Activity經過mView.post方法獲取server
mView.post(new Runnable() { @Override public void run() { int width = mView.getMeasuredWidth(); int height = mView.getMeasuredHeight(); } });
當View樹的狀態發生改變或者View樹內部View的可見性發生改變的時候,onGlobalLayout將會被回調。注意:伴隨着View樹的狀態改變,onGlobalLayout會被調用屢次。實現以下:
在Activity生命週期方法中經過ViewTreeObserver獲取對象
ViewTreeObserver observer = mView.getViewTreeObserver(); observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { mView.getViewTreeObserver().removeOnGlobalLayoutListener(this); int width = mView.getMeasuredWidth(); int height = mView.getMeasuredHeight(); } });
手動調用measure後,View會調用onMeasure方法對View發起測量,測量完後,就能夠獲取測量後的寬度和高度了。可是要對LayoutParams的參數分狀況處理才能獲得具體的參數值:
View的LayoutParams參數爲match_parent:這種狀況下沒法獲取到具體寬高值,由於當View的測量模式爲match_parent時,寬高值是取父容器的剩餘空間大小做爲它本身的寬高。而這時沒法獲取到父容器的尺寸大小,所以獲取會失敗。
View的LayoutParams參數爲具體值:
blog
int width =View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.EXACTLY); int height =View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.EXACTLY); view.measure(width,height); int height=view.getMeasuredHeight(); int width=view.getMeasuredWidth();
View的LayoutParams參數爲wrap_content:
生命週期
int width =View.MeasureSpec.makeMeasureSpec((1<<30)-1,View.MeasureSpec.AT_MOST); int height =View.MeasureSpec.makeMeasureSpec((1<<30)-1,View.MeasureSpec.AT_MOST); view.measure(width,height); int height=view.getMeasuredHeight(); int width=view.getMeasuredWidth();