从源码分析addView子控件match_parent失效问题

addView()方法使用心得

addView方法可以满足动态添加布局需求,于是乎就出现了布局加进去后不是我们想要的效果,我开始以为是我子布局设置了什么属性,仔细看了布局却发现没什么错误,所以猜想大概是addView时出了问题。
我的使用如下:

 View view = null;
        LayoutInflater layoutInflater = LayoutInflater.from(getContext());
        if (true) {
            view = layoutInflater.inflate(R.layout.layout_operate_bar_has, null);
        } else {
            view = layoutInflater.inflate(R.layout.layout_operate_bar_no, null);
        }
        if (llIntegral.getChildCount() != 0) {
            llIntegral.removeAllViews();
        }
        llIntegral.addView(view);

查看ViewGroup源码addView()方法

ViewGroup 类提供了addView五个重载方法分别如下

  /**
     * 

Adds a child view. If no layout parameters are already set on the child, the * default parameters for this ViewGroup are set on the child.

* *

Note: do not invoke this method from * {@link #draw(android.graphics.Canvas)}, {@link #onDraw(android.graphics.Canvas)}, * {@link #dispatchDraw(android.graphics.Canvas)} or any related method.

* * @param child the child view to add * * @see #generateDefaultLayoutParams() */
public void addView(View child) { addView(child, -1); } /** * Adds a child view. If no layout parameters are already set on the child, the * default parameters for this ViewGroup are set on the child. * *

Note: do not invoke this method from * {@link #draw(android.graphics.Canvas)}, {@link #onDraw(android.graphics.Canvas)}, * {@link #dispatchDraw(android.graphics.Canvas)} or any related method.

* * @param child the child view to add * @param index the position at which to add the child * * @see #generateDefaultLayoutParams() */
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); } /** * Adds a child view with this ViewGroup's default layout parameters and the * specified width and height. * *

Note: do not invoke this method from * {@link #draw(android.graphics.Canvas)}, {@link #onDraw(android.graphics.Canvas)}, * {@link #dispatchDraw(android.graphics.Canvas)} or any related method.

* * @param child the child view to add */
public void addView(View child, int width, int height) { final LayoutParams params = generateDefaultLayoutParams(); params.width = width; params.height = height; addView(child, -1, params); } /** * Adds a child view with the specified layout parameters. * *

Note: do not invoke this method from * {@link #draw(android.graphics.Canvas)}, {@link #onDraw(android.graphics.Canvas)}, * {@link #dispatchDraw(android.graphics.Canvas)} or any related method.

* * @param child the child view to add * @param params the layout parameters to set on the child */
@Override public void addView(View child, LayoutParams params) { addView(child, -1, params); } /** * Adds a child view with the specified layout parameters. * *

Note: do not invoke this method from * {@link #draw(android.graphics.Canvas)}, {@link #onDraw(android.graphics.Canvas)}, * {@link #dispatchDraw(android.graphics.Canvas)} or any related method.

* * @param child the child view to add * @param index the position at which to add the child or -1 to add last * @param params the layout parameters to set on the child */
public void addView(View child, int index, LayoutParams params) { if (DBG) { System.out.println(this + " addView"); } if (child == null) { throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup"); } // addViewInner() will call child.requestLayout() when setting the new LayoutParams // therefore, we call requestLayout() on ourselves before, so that the child's request // will be blocked at our level requestLayout(); invalidate(true); addViewInner(child, index, params, false); }

查看发现这五个方法都写在一起,挺好找的,相信看到这里,你也会和我一样恍然大悟,原来如此,通常我都是使用addView(View)一个参数的方法,如果我们不指定约束条件,系统就会默认为我们添加约束,


    /**
     * Adds a child view. If no layout parameters are already set on the child, the
     * default parameters for this ViewGroup are set on the child.
     *
     * 

Note: do not invoke this method from * {@link #draw(android.graphics.Canvas)}, {@link #onDraw(android.graphics.Canvas)}, * {@link #dispatchDraw(android.graphics.Canvas)} or any related method.

* * @param child the child view to add * @param index the position at which to add the child * * @see #generateDefaultLayoutParams() */
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)不指定约束,最后就会调用上面这个方法,最后会调用

    /**
     * Returns a set of default layout parameters. These parameters are requested
     * when the View passed to {@link #addView(View)} has no layout parameters
     * already set. If null is returned, an exception is thrown from addView.
     *
     * @return a set of default layout parameters or null
     */
    protected LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    }

给我们加进去的布局默认指定这个约束。

正确使用

 llIntegral.addView(view,new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));

当然我们也可以指定宽高,系统也为我们特意准了这个方法。

你可能感兴趣的:(android)