大家很多時候需要在Activity或者Fragment的onCreate()方法中獲取聲明的空間的高度或者寬度,進行位置移動或者其他操作,但是當調用 view.getHeight()
或者 view.getWidth()
獲取的竟然爲0。。。
其實很容易理解,在onCreate()的時候,實際上控件只是聲明瞭,並沒有繪製完成,沒有attach到window上,所以導致獲取的高度和寬度爲0
,那麼該怎麼解決呢?
三種方式
1、使用下面的post方式
view.post(new Runnable() {
@Override
public void run() {
int height = view.getHeight() ;
int width = view.getWidth();
}
});
原理:
-
View.post(Runnable) 內部會自動分兩種情況處理,當 View 還沒 attachedToWindow 時,會先將這些 Runnable 操作緩存下來;否則就直接通過 mAttachInfo.mHandler 將這些 Runnable 操作 post 到主線程的 MessageQueue 中等待執行。
-
如果 View.post(Runnable) 的 Runnable 操作被緩存下來了,那麼這些操作將會在 dispatchAttachedToWindow() 被回調時,通過 mAttachInfo.mHandler.post() 發送到主線程的 MessageQueue 中等待執行。
想了解更多請去查看源碼。相信你可以更深層次的理解。
View.post() 中的操作執行時,View 的寬高已經計算完畢,所以可以在 Activity 的 onCreate() 裏調用 View.post() 來解決獲取 View 寬高爲0的問題
。
2、使用ViewTreeObserver的方式
ViewTreeObserver vto = view.getRabbit().getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
if(vto.isAlive()){
vto.removeOnDrawListener(this);
}
int height = view.getMeasuredHeight());
return true;
}
});
ViewTreeObserver 註冊一個觀察者來監聽視圖樹,當視圖樹的佈局、視圖樹的焦點、視圖樹將要繪製、視圖樹滾動等發生改變時,ViewTreeObserver都會收到通知。所以 這個方法會調用很多次,如果要使用這種方法的話,要做好規避調用多次,記得移除監聽
;ViewTreeObserver不能被實例化,可以調用View.getViewTreeObserver()來獲得。
3、還有一種不太推薦
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
int height = view.getHeight()
int width = view.getHeight();
}
這個函數的含義是:view已經初始化完畢了,寬/高已經準備好了,這個時候去獲取寬高是可以成功獲取的。需要注意的是 onWindowFocusChanged函數會被調用多次,當Activity的窗口得到焦點和失去焦點時均會被調用一次,如果頻繁地進行onResume和onPause,那麼onWindowFocusChanged也會被頻繁地調用,不太適合處理一些複雜的業務邏輯
。