假如我們在Activity已經啟動完之后扁位,需要獲取一個View的寬/高≌咄可能大部分人都試過在onCreate块仆、onStart、onResume中獲取寬/高王暗,然而獲取的結果均為 0悔据。這是因為View的measure過程和Activity的生命周期并不是同步執(zhí)行的,因此無法保證在onCreate俗壹、onStart科汗、onResume中獲取寬/高時View已經測量完了,如果沒有測量完绷雏,獲得的寬/高就是0头滔。
我們用以下幾個方法解決這個問題:
一怖亭、Activity/View#onWindowFocusChanged
onWindowFocusChanged的含義:View已經初始化完畢了,寬/高已經準備好了坤检,這個時候獲取寬/高是沒有問題的兴猩。當Activity的當前Window獲得或失去焦點時會回調此方法,也就是說當Activity暫停執(zhí)行和繼續(xù)執(zhí)行都會回調此方法早歇,即這個方法會被頻繁調用倾芝。我們一般在第一次獲取焦點時獲取寬高,代碼如下:
private boolean isFirstFocus = true;
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus&&isFirstFocus){
isFirstFocus = false;
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
}
}
二箭跳、view.post(runnable)
利用 Handler 通信機制晨另,通過post將添加一個 Runnable到message queue的隊尾,當View初始化完成之后谱姓,Looper會調用此runnable借尿,然后通知UI線程。代碼如下:
@Override
protected void onStart() {
super.onStart();
view.post(new Runnable() {
@Override
public void run() {
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
}
});
}
三屉来、ViewTreeObserver
當View樹狀態(tài)發(fā)生改變路翻,或者View樹內部的view的可見性發(fā)生改變時,onGlobalLayout會被回調茄靠,所以這也是獲取寬高的一個很好的時機茂契。伴隨著View樹的狀態(tài)的改變,onGlobalLayout會被調用多次嘹黔,因此可在第一次調用完后账嚎,移除監(jiān)聽事件。代碼如下:
@Override
protected void onStart() {
Logger.e("onStart");
super.onStart();
ViewTreeObserver viewTreeObserver = view.getViewTreeObserver();
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
view.removeOnLayoutChangeListener(this);
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
}
});
}
四儡蔓、View#addOnLayoutChangeListener
監(jiān)聽 View的onLayout()的繪制過程郭蕉,一旦寬/高發(fā)生變化就會回調onLayoutChange方法。因此可在第一次調用完后喂江,移除監(jiān)聽事件召锈。代碼如下:
view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
view.removeOnLayoutChangeListener(this);
Logger.e("w/h:" + view.getWidth() + "-" + view.getHeight());
}
});