在自定义view时,测量过程中,view的MeasureSpec是由父容器的MeasureSpec和view自身的LayoutParams共同决定的。那么如果在动态添加view时,未给view设定LayoutParams时,系统是如何给view设置LayoutParams的呢?比如如下代码
LinearLayout root = (LinearLayout) inflater.inflate(R.layout.main,parentView,false);
TextView myView = new TextView(getActivity());
root.addView(myView);
动态的将一个TextView添加到一个LinearLayout中,这个时候,并未给TextView指定LayoutParams,但是TextView仍然可以被添加到LinearLayout中, 并显示一个大小,这就说明,TextView经过测量时,是有一个LayoutParams的,否则,就无法计算这个TextView的MeasureSpec了。像这种直接使用View的一个参数的构造函数创建的View,未直接指定view的LayoutParams的情况,由于view的specMode是根据父容器的specMode和view自身的LayoutParams来决定的,所以,这种动态添加视图的方式,view的LayoutParams也肯定是会指定的,点开root.addView(myview)这个方法,可以看到在ViewGroup类中的addView方法的实现如下:
public void addView(View child) {
addView(child, -1);
}
addView方法调用了重载方法addView(View child, int index),下面看看其具体实现
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);
}
这个方法中,可以看到view的layoutParams是由generateDefaultLayoutParams()方法生成的。ViewGroup类中的generateDefaultLayoutParams()的默认实现如下:
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}
由于每个具体的父容器都是继承自ViewGroup,这些具体的容器,根据自身的特性,对其父类ViewGroup的generateDefaultLayoutParams()进行重写,所以想要知道view的layoutParmas具体是多少,就要看view是被添加到了具体的哪个父容器,下面列出了常见的几个父容器的generateDefaultLayoutParams()的实现。
LinearLayout类中的generateDefaultLayoutParams()方法
@Override
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;
}
RelativeLayout类中的generateDefaultLayoutParams()方法
@Override
protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}
FrameLayout类中的generateDefaultLayoutParams()方法
@Override
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
ConstraintLayout类中generateDefaultLayoutParams()方法
protected ConstraintLayout.LayoutParams generateDefaultLayoutParams() {
return new ConstraintLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}
所以,想要知道view的具体LayoutParams,就需要知道其父容器的generateDefaultLayoutParams()方法的具体实现,就可以知道了。