今天做一个欢迎页面,发现ViewPage始终占据父容器LinearLayout的剩余高度。
网上的解决方案都是重写ViewPage的onMeasure()
public class WrapContentHeightViewPager extends ViewPager {
public WrapContentHeightViewPager(Context context) {
super(context);
}
public WrapContentHeightViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//以子page高度的最高值为ViewPage的高度
int height = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight() + this.getPaddingTop() + this.getPaddingBottom();
if (h > height) height = h;
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
高度要记得加上paddingTop和paddingBottom, 网上的解决方案里是没有的。这样会有问题。
如果你正好用到了paddingTop/paddingBottom, 那么ViewPage会被截掉一些,被截掉的高度正好是paddingTop+paddingBottom的值。
这儿再重点说一下MeasureSpec.UNSPECIFIED
有一些父容器是那种不限制子view高度的控件。比如ScrollView, ViewPage等。这类控件的内容高度是无限的。所以高度用wrap_content是没有效果的。要使wrap_content有效果,必须重写onMeasure(), 然后在测量子View的时候, 把MeasureSpec.UNSPECIFIED传给子View, 告诉子View你们的内容高度是多少就回报给我多少。然后父控件就拿到子View们的高度后,就可以设置父控件的高度了。 这样一来wrap_content就有用了。