动态添加view时,如果未指定view的LayoutParams,那么view的LayoutParams是如何生成的呢?

在自定义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()方法的具体实现,就可以知道了。

你可能感兴趣的:(android)