ViewPager 巢狀多個不同高度的Fragment,ViewPager 高度自適應
阿新 • • 發佈:2019-01-25
問題:
ViewPager 巢狀多個Fragment,但是每個Fragment高度不一致,導致高度比較小的Fragment底部留有大片空白區域。
解決方法:
參考文章 關於ViewPager高度自適應(隨著pager頁的高度改變Viewpager的高度)
ViewPager 常用重寫類:
1.viewpager巢狀在scrollview中,為了解決viewpager和scorllview的衝突,重寫的類
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, MeasureSpec.makeMeasureSpec(0 , MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
if (h > height)
height = h;
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
2.為了解決上述空白問題,首先定義一個CustomViewPager類,繼承自ViewPager,重寫onMeasure方法,重新計算高度
public class CustomViewPager 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 CustomViewPager(Context context)
{
super(context);
}
public CustomViewPager(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) {
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams();
if (layoutParams == null) {
layoutParams = new LinearLayout.LayoutParams(LinearLayout.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;
}
}
使用方法:
首先在Fragment裡呼叫setObjectForPosition方法,存放view和他對應的position:
private int fragmentID=0;
private View rootView=null;
public XXXXXFragment(CustomViewPager vp,int fragmentID)
{
this.vp = vp;
this.fragmentID =fragmentID;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
rootView = inflater.inflate(R.layout.fragment_chart_bp, container, false);
ButterKnife.bind(this, rootView);
vp.setObjectForPosition(rootView,fragmentID);
return rootView;
}
如果從服務端獲取資料,得到資料後,重新繪製Fragment,比如顯示線形圖,或者顯示資料為空的提示之類的,需要在繪製之後,重新呼叫
vp.setObjectForPosition(rootView,fragmentID);
在設定ViewPager時,如果繪製有延遲,需要延遲呼叫viewPager.resetHeight(position);
private LinkedHashMap<String, Fragment> titleFragmentMap = new LinkedHashMap<>();
private Fragment fragment1, fragment2, fragment3;
fragment1 = new XXXXXFragment(viewPager,0);
fragment2 = new XXXXXFragment(viewPager,1);
fragment3 = new XXXXXFragment(viewPager,2);
titleFragmentMap.put("日", fragment1);
titleFragmentMap.put("周", fragment2);
titleFragmentMap.put("月", fragment3);
pagerAdapter = new MyFragmentPageAdapter(getChildFragmentManager(), titleFragmentMap);
viewPager.setAdapter(pagerAdapter);
viewPager.setOffscreenPageLimit(3);
viewPager.setCurrentItem(1);
viewPager.addOnPageChangeListener(this);
tabLayout.setupWithViewPager(viewPager);
tabLayout.post(new Runnable()
{
@Override
public void run()
{
TabLayoutUtil.setUpIndicatorWidth(getContext(), tabLayout, 20, 20);
viewPager.resetHeight(1);
}
});
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{
}
@Override
public void onPageSelected(int position)
{
viewPager.resetHeight(position);
setInitLineChart();
}
@Override
public void onPageScrollStateChanged(int state)
{
}