一个关于NestedScrollView中嵌套ViewPager,ViewPager高度显示不全的解决方案(根据View设置高度)

1、当页面中有滚动的布局嵌套时,比如根布局是scrollView或NestedScrollView,这个时候页面下方有一个可以切换的tab标签页,这个时候大多数会采用ViewPager+fragment来实现。

这个时候我们会发现一个问题,首先:

问题1
在滑动的布局中嵌套ViewPager后,ViewPager中的内容不显示
,也就是高度为0了,这个时候需要我们自己自义定一个Viewpager来重新获取ViewPager的高度,在OnMearsure中对高度进行重新测量:

于是有了自定义的ViewPager

public class CustomViewPager extends ViewPager {
 
   public CustomViewPager(Context context) {
      super(context);
   }
 
   public CustomViewPager(Context context, AttributeSet attrs) {
      super(context, attrs);
   }
 
   @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, View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
         int h = child.getMeasuredHeight();
         if (h > height)
            height = h;
      }
 
      heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
 
      super.onMeasure(widthMeasureSpec, heightMeasureSpec);
   }
}

可以看出,此自定义ViewPager的高度是根据子view的高度来决定的, if (h > height) height = h;循环过后,就是将高度最大的子view的高度赋值给ViewPager的高度,这样可以解决ViewPager不显示的问题,但是又出现了一个新的
问题2
比如切换tab页中的数据有的比较少的时候,也就是fragment中的view的高度小的时候,ViewPager中的view的高度还是前面最大的那个高度,所以在它的下面会留下一段很长的空白。

接下来对ViewPager进行加工:

public class AutoHeightViewPager extends ViewPager {

    private int current;
    private int height = 0;
    /**
     * 保存position与对于的View
     */
    private HashMap<Integer, View> mChildrenViews = new LinkedHashMap<Integer, View>();

    private boolean scrollble = true;

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

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


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (mChildrenViews.size() > current) {
            View child = mChildrenViews.get(current);
            child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
            height = child.getMeasuredHeight();
        }

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

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    public void resetHeight(int current) { this.current = current; if (mChildrenViews.size() > current) { ViewGroup.LayoutParams layoutParams = (ViewGroup.LayoutParams) getLayoutParams(); if (layoutParams == null) { layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height); } else { layoutParams.height = height; } setLayoutParams(layoutParams); } }
    /**
     * 保存position与对于的View
     */
    public void setObjectForPosition(View view, int position)
    {
        mChildrenViews.put(position, view);
    }


    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (!scrollble) {
            return true;
        }
        return super.onTouchEvent(ev);
    }


    public boolean isScrollble() {
        return scrollble;
    }

    public void setScrollble(boolean scrollble) {
        this.scrollble = scrollble;
    }

}

重要方法: setObjectForPosition()记录view高度与位置
resetHeight() 重置ViewPager高度

如何使用:

1.activity中初始化:

将ViewPager的引用传入到fragment中

        personFragments = FragmentUtil.getPersonListFragment(viewPager,userUid);
        viewPager.setAdapter(new TabsPagerAdapter(getSupportFragmentManager(),        personFragments));
        viewPager.addOnPageChangeListener(this);
        viewPager.setOffscreenPageLimit(2);
        viewPager.setCurrentItem(0);
public static List<Fragment> getPersonListFragment(AutoHeightViewPager viewPager,long userUid) {
        List<Fragment> fragmentList = new ArrayList<>();
        fragmentList.add(UserPostFragment.newInstance(viewPager,userUid));
        fragmentList.add(UserQaFragment.newInstance(viewPager,userUid));
        return fragmentList;
    }

2.fragment中拿到viewPager的引用(重写构造方法),重写onCreateView方法,
oncreateView方法中调用: viewPager.setObjectForPosition(rootView,0);//0代表tab的位置 0,1,2,3

public class UserPostFragment extends BaseFragment {

    public static UserPostFragment newInstance(AutoHeightViewPager viewPager,long userUid) {
        Bundle bundle = new Bundle();
        bundle.putString("item","UserPostFragment");
        bundle.putLong(Constant.UID, userUid);
        UserPostFragment fragment = new UserPostFragment(viewPager);
        fragment.setArguments(bundle);
        return fragment;
    }
    
    @SuppressLint("ValidFragment")
    public UserPostFragment(AutoHeightViewPager viewPager) {
        this.viewPager=viewPager;
    }
 }   

 @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        rootView=super.onCreateView(inflater, container, savedInstanceState);
        viewPager.setObjectForPosition(rootView,0);//0代表tab的位置 0,1,2,3
        return rootView;
    }

3.activity中Viewpager设置的监听事件,onPageSelected方法中,调用 resetHeight方法

viewPager.addOnPageChangeListener(this);

@Override
    public void onPageSelected(int position) {
        viewPager.resetHeight(position);
        switch (position){
            case 0:
                setRbStatus(true,false);
                break;
            case 1:
                setRbStatus(false,true);
                break;
        }
    }
  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值