前言
很多時候,我們在動態(tài)創(chuàng)建View時,需要獲取View的寬高。這時,如果你在onCreate、onStart、onResume中直接調(diào)用View的getWidth/getHeight方法,均無法得到View寬/高的正確信息。這是因?yàn)関iew的measure過程與Activity的生命周期是不同步的。這就無法保證在onCreate、onStart、onResume中view的measure已經(jīng)完成。若view的measure此時正在進(jìn)行,那么獲得的寬/高就是0。這里我將給出三種方案來解決這個問題。
萬能的view.post()方法。
曾經(jīng)有個同事對我說過這樣一句話,他說,在他遇到各種莫名奇妙的UI問題的時候,他最先嘗試的就是view.post方法,而且有效率極高。當(dāng)然,view.post方法在解決這個問題上也是有效的。將一個runnable對象放到主線程的末尾去執(zhí)行,這時view已經(jīng)measure、layout、draw完成。因此,此方法是有效的。代碼如下:
view.post(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
int width = view.getWidth();
int hight = view.getHeight();
}
});
Activity的onWindowFocusChanged方法
onWindowFocusChanged,通過名字我們就可以推測出該方法的含義:當(dāng)Activity的窗口得到焦點(diǎn)或者失去焦點(diǎn)的時候會調(diào)用該方法一次。當(dāng)Activity獲取焦點(diǎn)時,說明View已經(jīng)初始化完畢。此時,調(diào)用view的getWidth()/getHeight()方法是沒有問題的。需要注意的是,若Activity頻繁的失去、得到焦點(diǎn)那么該方法會被頻繁的調(diào)用。
@Override
public void onWindowFocusChanged(boolean hasFocus) {
// TODO Auto-generated method stub
super.onWindowFocusChanged(hasFocus);
if(hasFocus){
int width = view.getWidth();
int hight = view.getHeight();
}
}
為ViewTreeObserver注冊O(shè)nGlobalLayoutListener接口
ViewTreeObserver是一個觀察者,主要是用來觀察視圖樹的各種變化。OnGlobalLayoutListener的作用是當(dāng)View樹的狀態(tài)發(fā)生改變或者View樹中某view的可見性發(fā)生改變時,OnGlobalLayoutListener的onGlobalLayout方法將會被回調(diào)。因此,此時獲取view的寬/高也是可以的。與onWindowFocusChanged類似,當(dāng)view樹的狀態(tài)多次發(fā)生改變時,onGlobalLayout會被調(diào)用多次。
ViewTreeObserver observer = title_name.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// TODO Auto-generated method stub
int width = view.getWidth();
int hight = view.getHeight();
}
});
參考書籍
Anroid開發(fā)藝術(shù)探索