Android的Activity獲取View寬高的常用方式

假如我們在Activity已經(jīng)啟動完之后,需要獲取一個View的寬/高。可能大部分人都試過在onCreate、onStart、onResume中獲取寬/高,然而獲取的結(jié)果均為 0。這是因?yàn)閂iew的measure過程和Activity的生命周期并不是同步執(zhí)行的,因此無法保證在onCreate、onStart、onResume中獲取寬/高時View已經(jīng)測量完了,如果沒有測量完,獲得的寬/高就是0。
我們用以下幾個方法解決這個問題:

一、Activity/View#onWindowFocusChanged

onWindowFocusChanged的含義:View已經(jīng)初始化完畢了,寬/高已經(jīng)準(zhǔn)備好了,這個時候獲取寬/高是沒有問題的。當(dāng)Activity的當(dāng)前Window獲得或失去焦點(diǎn)時會回調(diào)此方法,也就是說當(dāng)Activity暫停執(zhí)行和繼續(xù)執(zhí)行都會回調(diào)此方法,即這個方法會被頻繁調(diào)用。我們一般在第一次獲取焦點(diǎn)時獲取寬高,代碼如下:

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 通信機(jī)制,通過post將添加一個 Runnable到message queue的隊(duì)尾,當(dāng)View初始化完成之后,Looper會調(diào)用此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

當(dāng)View樹狀態(tài)發(fā)生改變,或者View樹內(nèi)部的view的可見性發(fā)生改變時,onGlobalLayout會被回調(diào),所以這也是獲取寬高的一個很好的時機(jī)。伴隨著View樹的狀態(tài)的改變,onGlobalLayout會被調(diào)用多次,因此可在第一次調(diào)用完后,移除監(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ā)生變化就會回調(diào)onLayoutChange方法。因此可在第一次調(diào)用完后,移除監(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());
    }
});
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容