ViewPager之可变高度ViewPager

来源:互联网 发布:手机淘宝6.10.3 编辑:程序博客网 时间:2024/05/21 21:10

项目中用到动态高度的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切换和初始获取,动态改变为我们的高度

原创粉丝点击