带有动态页面高度的ScrollView中的ViewPager

时间:2018-06-28 23:58:43

标签: android android-viewpager android-scrollview android-pageradapter

我已经阅读了许多其他的答案,但似乎没有什么是我想要的。我想要的是ScrollView内的ViewPager,每个页面的高度都适合该内容。关于SO的一些更受欢迎的答案似乎必须采用ViewPager中子级的最大高度,但这会导致空白。

WrapContentViewPager

public class WrapContentViewPager extends ViewPager {


public WrapContentViewPager(Context context) {
    super(context);
}

public WrapContentViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int height = 0;
    View view = null;
    for(int i = 0; i < getChildCount(); i++) {
        view = getChildAt(i);
        view.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
        int h = view.getMeasuredHeight();
        if(h > height) height = h;
    }

    if (height != 0) {
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
    }

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    setMeasuredDimension(getMeasuredWidth(), measureHeight(heightMeasureSpec, view));
}


/**
 * Determines the height of this view
 *
 * @param measureSpec A measureSpec packed into an int
 * @param view the base view with already measured height
 *
 * @return The height of the view, honoring constraints from measureSpec
 */
private int measureHeight(int measureSpec, View view) {
    int result = 0;
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);

    if (specMode == MeasureSpec.EXACTLY) {
        result = specSize;
    } else {
        // set the height from the base view if available
        if (view != null) {
            result = view.getMeasuredHeight();
        }
        if (specMode == MeasureSpec.AT_MOST) {
            result = Math.min(result, specSize);
        }
    }
    return result;
}

}

之所以不起作用,是因为如果我转到第三页,该页的高度很大,列表中有32个项目,然后返回第二页,只有3个项目,则有很多由于第二页的高度为最大值,因此第二页中的空白空间。

我已经在https://github.com/rnevet/WCViewPager的GitHub上尝试了WCViewPager库,但它对我也不起作用。

有人可以指导我找到正确的解决方案吗?顺便说一下,我使用的是ViewPager和PagerAdapter,而不是FragmentPagerAdapter。

更新

我想出了一种更好的解决方法。

`公共类WrapContentViewPager扩展了ViewPager {

public WrapContentViewPager(Context context) {
    super(context);
}

public WrapContentViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int mode = MeasureSpec.getMode(heightMeasureSpec);
    // Unspecified means that the ViewPager is in a ScrollView WRAP_CONTENT.
    // At Most means that the ViewPager is not in a ScrollView WRAP_CONTENT.
    if (mode == MeasureSpec.UNSPECIFIED || mode == MeasureSpec.AT_MOST) {
        // super has to be called in the beginning so the child views can be initialized.
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int position = getCurrentItem();
        View child = this.findViewWithTag("view"+position);
        child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
        int height = child.getMeasuredHeight();
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
    }
    // super has to be called again so the new specs are treated as exact measurements
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

}`

在我的PagerAdapter中,我更改了方法instantiateItem

 @Override
public @NonNull Object instantiateItem(@NonNull ViewGroup view, int position) {
    View layout = inflater.inflate(R.layout.layout, view, false);
    layout.setTag("view" + position);
}

此解决方案会在每次移动时重新测量当前页面的高度。 getChildAt(getCurrentItem())给出不同的结果,因此不可靠。

0 个答案:

没有答案