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;
}
}