在自定義View時碰到的奇怪問題

xiasuhuei321發表於2017-12-13

最近在擼新的東西玩,自定義View我也算是半個老司機了。首先在onMeasure中處理了wrap_content的情況,然後我驚奇的在log中發現,我測量出來的結果竟然是1080?這是什麼操作?後來除錯發現測量寬度時進入了精確模式,沒跑了肯定是match_parent。我是怎麼把View新增到父View的呢?程式碼如下:

ll_container!!.addView(v)
複製程式碼

這是一個LinearLayout,不說多的點進addView看一下:

    public void addView(View child) {
        addView(child, -1);
    }

    public void addView(View child, int index) {
        if (child == null) {
            throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup");
        }
        LayoutParams params = child.getLayoutParams();
        if (params == null) {
            params = generateDefaultLayoutParams();
            if (params == null) {
                throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null");
            }
        }
        addView(child, index, params);
    }
複製程式碼

可以看到首先addView(View)方法呼叫了過載方法,並在在新增之前判斷了LayoutParams,如果為null則生成一個,不為null則新增到ViewGroup中。我這裡沒有設定LayoutParams,所以必定為null,那看一下生成引數的程式碼吧:

    protected LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    }
複製程式碼

納尼???看到這真是黑人問號了,倆wrap_content進入了exactly測量模式,除非Android系統爆炸還差不多。後來突然想起來Java有一種玩意叫做後期繫結,可能是LinearLayout複寫了這個生成引數的方法,點進LinearLayout搜尋了一下,果然如此:

    protected LayoutParams generateDefaultLayoutParams() {
        if (mOrientation == HORIZONTAL) {
            return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        } else if (mOrientation == VERTICAL) {
            return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        }
        return null;
    }
複製程式碼

沒辦法,剛好設定的vertical方向,果然width設定了match_parent。看來以後還是要多瞭解一下ViewGroup。

相關文章