安卓 onCreate 方法獲取 view 寬高的方法

我們在開發(fā)中經(jīng)常會(huì)遇到在界面中比如 activity 使用到控件的 width 或者 height,大家也都知道在 onCreate() 中去 getWidth() 或者是 getMeasuredWidth() 拿到的結(jié)果都是 0,這是因?yàn)槲覀兊?activity 的創(chuàng)建和 view 繪制不是同步的,下面我總結(jié)了一些方法來獲取 view 的寬度和高度的方法:

  • View.Post(new Runnable()) 方法
    這個(gè)方法并不是新啟動(dòng)一個(gè)線程,SDK 中對這個(gè)方法的注釋為 Causes the Runnable to be added to the message queue. The runnable will be run on the user interface thread. 意思是在消息隊(duì)列中添加一個(gè) runnable ,這個(gè) runnable 在用界面線程上執(zhí)行,也就是我們常說的安卓UI線程,那么我們將這個(gè) runnable 插入到消息隊(duì)列的末端,然后當(dāng) view 的 measure(),layout(),draw()執(zhí)行完后調(diào)用我們在 runnable 中獲取寬高的方法,就是準(zhǔn)確的值了。缺點(diǎn)是方法不能及時(shí)執(zhí)行。

  • Activity 的 onWindowFocusChanged() 方法
    當(dāng)活動(dòng)的當(dāng)前窗口獲得或失去焦點(diǎn)時(shí)調(diào)用。這是該活動(dòng)是否對用戶可見的最好指標(biāo)。
    這個(gè)方法的含義是,view 已經(jīng)初始化完畢了,這個(gè)時(shí)候取獲取寬/高是沒問題的。需要注意的是 onWindowFocusChanged 會(huì)被調(diào)用多次,當(dāng) Activity 的窗口得到焦點(diǎn)和失去焦點(diǎn)時(shí)均會(huì)被調(diào)用一次,就具體來說,當(dāng) activity 繼續(xù)執(zhí)行和暫停執(zhí)行都會(huì)被調(diào)用,如果頻繁地進(jìn)行 onResume 和 onPause ,那么 onWindowFocusChange 也會(huì)頻繁調(diào)用。
    代碼如下:

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus) {
            int measuredHeight = view.getMeasuredHeight();
        }
    }
  • getViewTreeObserver().addOnGlobalLayoutListener()
    代碼如下:
        view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
        });
  • getViewTreeObserver().addOnPreDrawListener()
    代碼如下:
        view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                return false;
            }
        });
  • 通過 LayoutParams 獲取
    對于在XML文件里設(shè)置了具體寬高的 View 可以通過view.getLayoutParams().height/width 獲取到寬高。如果沒有設(shè)置具體寬高的話就不能用這個(gè)方法了。

  • 通過 view 自身的測量方法 Measure()
    通過手動(dòng)對 view 進(jìn)行 measure 來得到寬高。這個(gè)方法得根據(jù) view 的 LayoutParams 來區(qū)分:

match_parent
無法 measure 出具體的寬高。因?yàn)檫@個(gè)情況下,我們無法得到父容器的剩余空間,無法知道 parentSize ,所以不可能測量到 view 的大小,這個(gè)情況可以用上述其他方式來獲取。

具體的數(shù)值(dp/px)

int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY);
        int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(200, View.MeasureSpec.EXACTLY);
        view.measure(widthMeasureSpec, heightMeasureSpec);
 

wrap_content

int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec((1 << 30) - 1, View.MeasureSpec.AT_MOST);
        int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec((1 << 30) - 1, View.MeasureSpec.AT_MOST);
        view.measure(widthMeasureSpec, heightMeasureSpec);

注意 (1 << 30) - 1,通過分析 MeasureSpec 的實(shí)現(xiàn)我們知道,View 的尺寸使用30位二進(jìn)制表示,也就是說最大是30個(gè)1,即(2^30-1),也就是 (1 << 30) - 1,在最大化模式下,我們用 View 理論上能支持的最大值去構(gòu)造 MeasureSpec 是合適的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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