Android - 更新具有 child 不同高度的 ViewPager

Android - Update ViewPager whith child of different heights

我实现了一个没有片段(只是视图)的 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);
    }

问题是它为每个页面设置了相同的高度。我需要每个页面的自定义高度,具体取决于列表的高度。

我也尝试在 ViewPager 上使用 setOnPageChangeListener 调用 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>

感谢大家的帮助,

ViewPager 高度不能像您希望的那样每页变化。您可以尝试继承 ViewPager 以添加此功能,但处理不同大小页面之间的视觉转换将非常繁琐。另一种选择可能是在每次页面更改时重新测量 ViewPager(但我希望转换看起来很糟糕)。您需要设置页面更改侦听器,然后在 ViewPager 上调用 requestLayout。您的 ViewPager onMeasure 只需要找到当前可见子项的高度,并将 ViewPager 高度设置为与之匹配。

旁白:我没看到你在任何地方打电话给setMeasuredDimension。测量视图时,必须使用计算出的宽度和高度调用此方法,以通知视图测量的尺寸。当前,您正在自定义 onMeasure 末尾调用 super.onMeasure,这虽然有效,但意味着 ViewPager 将始终使用 "default" 宽度和高度进行测量。在这种情况下,它恰好与最大页面的高度相匹配。

有关详细信息,请参阅 onMeasure 的文档。特别是:

CONTRACT: When overriding this method, you must call setMeasuredDimension(int, int) to store the measured width and height of this view. Failure to do so will trigger an IllegalStateException, thrown by measure(int, int). Calling the superclass' onMeasure(int, int) is a valid use.

我只是找到了可以胜任的东西。

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

页面大小是固定的,但滚动视图可以解决问题...

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>

"Page item" :

<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(更多信息 here):

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