ViewPager之可变高度ViewPager

项目中用到动态高度的ViewPager,为了加强记忆,自己也仿着写个效果来

原理:

        ViewPager默认是每个页面相同高度的,我们要改变其页面的高度,

        自然就要在其显示某个页面的时候调用其(ViewPager)的onMeasure方法。

        本文基于这个观点,在每次选择页面后将当前页面(Fragment)的rootView传递到ViewPager中,

        让ViewPager根据该rootView,一般是ViewGroup类型,去重新执行onMeasure方法

1、传递给ViewPager中页面的rootView;

2、ViewPager获取到rootView后调用requestLayout方法使ViewPager再次调用onMeasure方法

3、重写ViewPager的onMeasure方法,根据rootView获取其总高度,传递给ViewPager

先上布局:

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

    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>


</LinearLayout>

我图省事,没有新建Activity,是在Fragment中测试的,所以这个布局是Fragment的布局

ViewPager的代码

public class DynamicHeightViewPager extends ViewPager {

    private ViewGroup mContainer;

    public DynamicHeightViewPager(@NonNull Context context) {
        super(context);
    }

    public DynamicHeightViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public void measuredCurrentView(ViewGroup viewGroup){
        this.mContainer = viewGroup;
        requestLayout();//重新布局,触发onMeasure
    }

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

        if (mContainer == null) {//ViewPager自动绘制是调用默认的即可
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            return;
        }

        int  height = 0;//以下为测量rootView高度传递给viewPager
        for (int i = 0; i < mContainer.getChildCount(); i++) {
            View child = mContainer.getChildAt(i);
            if (child != null) {
                child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
                height += child.getMeasuredHeight();
            }
        }

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

        super.onMeasure(widthMeasureSpec,heightMeasureSpec);

    }
}

测试代码

mAdapter = new TabAdapter(getChildFragmentManager());

        mViewPager.setAdapter(mAdapter);

        mTabLayout.setupWithViewPager(mViewPager);

        //to measure height realize dynamic height
        mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                super.onPageSelected(position);
                if (position > mAdapter.getCount() || mViewPager == null || mHeader == null)
                    return;
                MyContentFragment fragment = (MyContentFragment) mAdapter.getItem(position);
                mViewPager.measuredCurrentView(fragment.getContainer());
                ViewGroup.LayoutParams params = mHeader.getLayoutParams();
            }
        });

        //coordinate the onPageSelected,the first show time is called
        mViewPager.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                MyContentFragment fragment = (MyContentFragment) mAdapter.getItem(0);
                if (mViewPager != null && fragment != null && mHeader != null) {
                    mViewPager.measuredCurrentView(fragment.getContainer());
                }
                if (mViewPager != null && mViewPager.getViewTreeObserver() != null) {
                    mViewPager.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                }
            }
        });


class TabAdapter extends FragmentPagerAdapter {

        TabAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            return mFragments.get(position);
        }

        @Override
        public int getCount() {
            return mFragments.size();
        }
    }

注:其中 1、mViewPager.addOnPageChangeListener()方法是在ViewPager滑动的时候触发,此时我们将rootView传递到ViewPager中,使ViewPager重新测量高度;但是 2、OnPagerChangeListener方法在ViewPager第一次显示时不会触发,通过mViewPager.getViewTreeObserver().addOnGlobalLayoutListener()方法可以在整个布局layout结束后调用,从而实现ViewPager显示出来就会被我们重新调用onMeasure方法,实现动态改变高度

通过两个监听结合可以实现对ViewPager切换和初始获取,动态改变为我们的高度

猜你喜欢

转载自blog.csdn.net/qq_34696209/article/details/78822645
今日推荐