ViewFlipper 子项高度均Match父类的问题探究

先说结果:setMeasureAllChildren(false).可以让子View适应自己的高度。

查看源码可以发现。ViewFlipper的父类ViewAnimator是继承与FrameLayout.

1.能控制View的宽高的话,先去onMeasure看看。

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int count = getChildCount();

        final boolean measureMatchParentChildren =
                MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY ||
                MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY;
        mMatchParentChildren.clear();

        int maxHeight = 0;
        int maxWidth = 0;
        int childState = 0;

        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            if (mMeasureAllChildren || child.getVisibility() != GONE) {
                //这里就开始用父类的spec来计算子类了。
                //所以,若不想与父类高度相同,就不能执行这里。
                //显然mMeasureAllChildren 是个开关,false掉即可
                measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
                //...
                // matchParentChildren 顾名思义,猜测下面应该对队列中的所有view来个measure.
                if (measureMatchParentChildren) {
                    if (lp.width == LayoutParams.MATCH_PARENT ||
                            lp.height == LayoutParams.MATCH_PARENT) {
                        mMatchParentChildren.add(child);
                    }
                }
            }
        }
        //...
        count = mMatchParentChildren.size();
        if (count > 1) {
            for (int i = 0; i < count; i++) {
                final View child = mMatchParentChildren.get(i);
                //...
                //果然
                child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
            }
        }
    }

2.对子类直接进行layout()或者奇葩的调用addView(width,height) 也会改变宽高。

虽然在onLayout发现有调用layout.但是宽高并没有变。还是Measure的宽高。

final int width = child.getMeasuredWidth();
final int height = child.getMeasuredHeight();
//...
child.layout(childLeft, childTop, childLeft + width, childTop + height);

 

3.接下来检查一下默认值。在FrameLayout中。

boolean mMeasureAllChildren = false;
 if (a.getBoolean(com.android.internal.R.styleable.FrameLayout_measureAllChildren, false)) {
            setMeasureAllChildren(true);
        }

可见其默认值是false.那肯定在ViewAnimator或ViewFlipper中设为true的。

ViewAnimator

final boolean measureAllChildren = a.getBoolean(
                com.android.internal.R.styleable.FrameLayout_measureAllChildren, true);
setMeasureAllChildren(measureAllChildren)

 

果然。。。

3.编译运行。问题解决。

4.回顾:可见ViewAnimator的子类都有会这一特质。也可以反向设置true使得子View通通match父类.

 关于measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);的细节可以看View源码。

 如果MeasureSpec不熟的话先去恶补一下吧。


posted @ 2013-03-14 12:51  wFeng  阅读(533)  评论(0编辑  收藏  举报