Android - 更新ViewPager中高度不同子项的方法

3

我有一个没有使用Fragment(只有视图)实现的ViewPager。每个页面都包含元素列表,但是这个列表并不总是具有相同的大小。

我尝试使用以下代码设置ViewPager的尺寸(扩展ViewPager以便可以重写此函数):

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        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();
            if(h > height) height = h;
        }

        heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

问题在于它为每个页面设置了相同的高度。我需要根据列表高度为每个页面设置自定义高度。
我还尝试使用setOnPageChangeListener在ViewPager上调用requestLayout()invalidate(),但大小仍然相同。也许我做错了...
这是一些可能有用的代码:
我的PagerAdapter的一部分:
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            // Inflate a new layout from our resources
            View view = getActivity().getLayoutInflater().inflate(R.layout.fragment_home_pager,
                    container, false);

            mContainerView = (ViewGroup) view.findViewById(R.id.news_container);
            reloadNews(position);

            // Add the newly created View to the ViewPager
            container.addView(view);

            // Return the View
            return view;
        }

我的XML布局的一部分:

        <ScrollView
            android:id="@+id/news_scrollview"
            android:layout_width="match_parent"
            android:layout_height="fill_parent">

            <com.ViewPagerWithHeight
                android:id="@+id/viewpager"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@android:color/white"/>

        </ScrollView>

非常感谢你的帮助。

为什么每个页面需要不同的高度?你想要实现什么目标? - Andrew Orobator
每个页面上都有一个新闻列表(为了简化:一个页面就像一个类别)。每个页面的新闻数量不同。ViewPager位于ScrollView内部。由于此代码为每个页面设置相同的大小(最大的那个),即使没有要滚动的元素(有一些空白空间),我也能向下滚动。 - DavidL
你能否翻转你的布局,将ScrollView放在ViewPager内部? - stkent
尝试以下答案。我已经尝试过了,它可以正常工作 https://dev59.com/t1wY5IYBdhLWcg3wspdj#32410274 - Nikhil Gupta
以下链接中的答案似乎完美地解决了这个问题: https://dev59.com/t1wY5IYBdhLWcg3wspdj#32410274 - Nikhil Gupta
2个回答

1

ViewPager 的高度不能随每个页面而变化,您可能会尝试对 ViewPager 进行子类化以添加此功能,但处理不同大小页面之间的视觉转换将非常棘手。另一种选择可能是在每次页面更改时重新测量 ViewPager(但我预计过渡效果会看起来相当糟糕)。您需要设置一个页面更改监听器,然后调用 ViewPager 上的 requestLayout 方法。您的 ViewPager onMeasure 需要仅找到当前可见子项的高度,并将 ViewPager 高度设置为与其匹配。

顺便说一下:我没有看到您在任何地方调用 setMeasuredDimension。在测量视图时,您必须使用计算出的宽度和高度调用此方法,以通知视图它已被测量到的大小。目前,在自定义 onMeasure 结束时,您正在调用 super.onMeasure,这是有效的,但意味着 ViewPager 将始终使用“默认”宽度和高度进行测量。在这种情况下,它恰好与最大页面的高度相匹配。

请参阅onMeasure文档获取更多详细信息。特别地: 合约:重写此方法时,您必须调用setMeasuredDimension(int, int)以存储此视图的测量宽度和高度。否则将会触发IllegalStateException异常,由measure(int, int)抛出。调用超类的onMeasure(int, int)是有效的使用方式。

我刚试了一下,问题还是一样:所选高度是最大的,而且应用于所有页面...即使您建议另一种设置测量尺寸的方法,高度值仍然相同。 - DavidL
感谢澄清,我会编辑答案以反映这一点。如果你考虑ViewPager的工作原理,这是有道理的。我们是通过这种方式设置整个ViewPager的大小。所以我的想法是:(1)使用默认的ViewPager无法实现您要寻找的内容;(2)在页面转换过程中,在什么时候ViewPager可以“改变高度”并不清楚,否则它看起来很奇怪;(3)您可以尝试覆盖ViewPager并自己处理每页的大小,但处理情况(2)可能需要很多努力。 - stkent
刚刚在答案中又添加了一个建议——虽然不是很出色,但可能是一个好的开始。 - stkent

0

我刚刚发现了一些可以完成工作的东西。

我将ScrollView移动到pageItem.xml中,这样我就可以设置页面大小(对于所有页面),但如果列表足够长,则仍然可以滚动。 ViewPager现在位于FrameLayout中,其中layout_height = fill_parent

页面大小是固定的,但ScrollView却起到了作用...

ViewPager(在我的片段内):

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="fill_parent"
    android:id="@+id/viewpagercontainer">

    <com.ViewPagerWithHeight
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/white"/>

</FrameLayout>

"页面元素":

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/news_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:showDividers="middle"
        android:divider="?android:dividerHorizontal" />

</ScrollView>

onMeasure函数:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

    heightMeasureSpec = MeasureSpec.makeMeasureSpec(containerHeight, MeasureSpec.EXACTLY);
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

如何设置属性containerHeight(更多信息在这里):

final View pagerContainer = (View) mView.findViewById(R.id.viewpagercontainer);
pagerContainer.post(new Runnable() {
    @Override
    public void run() {
        mViewPager.setContainerHeight(pagerContainer.getMeasuredHeight());
    }
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接