先说结果: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不熟的话先去恶补一下吧。