Fork me on GitHub

在自定义View时碰到的奇怪问题

最近在撸新的东西玩,自定义View我也算是半个老司机了。首先在onMeasure中处理了wrap_content的情况,然后我惊奇的在log中发现,我测量出来的结果竟然是1080?这是什么操作?后来调试发现测量宽度时进入了精确模式,没跑了肯定是match_parent。我是怎么把View添加到父View的呢?代码如下:

1
ll_container!!.addView(v)

这是一个LinearLayout,不说多的点进addView看一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    public void addView(View child) {
addView(child, -1);
}
<!--more-->

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,那看一下生成参数的代码吧:

1
2
3
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}

纳尼???看到这真是黑人问号了,俩wrap_content进入了exactly测量模式,除非Android系统爆炸还差不多。后来突然想起来Java有一种玩意叫做后期绑定,可能是LinearLayout复写了这个生成参数的方法,点进LinearLayout搜索了一下,果然如此:

1
2
3
4
5
6
7
8
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。