高度自适应的ViewPager--SelfAdaptingViewPager

       之前项目遇到了一个需求,需要scrollview里面嵌套一个viewpager,而且要做到切换viewpager的时候恰好完全展示对应的page。

       在网上搜索了很久,只看到某位大神提供的CustomViewPager,代码如下:  

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

      研究一番后发现,onMeasure方法中最后记录的是所有page多次测量后高度中的最大值,这样两个高度不一的page虽然都能完全展示,但是高度矮的那个就会有留白,不符合我们恰好展示的需求。

      于是我对代码进行了修改,有了SelfAdaptingViewPager,代码如下:  

public class SelfAdaptingViewPager extends ViewPager {
    private Map<Integer, Integer> map             = new HashMap<>(2);
    private int                   currentPosition = 0;
    private MarginLayoutParams params;

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

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

    //在View的绘制过程中此方法会被多次调用,每次都会测量出新的数据,我们用最新的数据替换旧的数据  
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
            int h = child.getMeasuredHeight();
            Log.d("SelfAdaptingViewPager", "measuredHeight=" + h);
            Log.d("SelfAdaptingViewPager", "getChildCount=" + getChildCount());
            Log.d("SelfAdaptingViewPager", "getChildAt(i)=" + i);  
           /* Log.d("SelfAdaptingViewPager", "getChildAt(i).getId())=" + getChildAt(i).getId()); 
            if (Build.VERSION.SDK_INT > 19) { 
                map.put(Math.abs(i - 1), h); 
            } else {*/
            map.put(i, h);
            //            }  
        }
        int height = 0;
        //onMeasure第一次被调用的时候,遍历不到child(View的绘制流程只是了解最基本的,我就不解释了)  
        height = map.get(currentPosition) == null ? 0 : map.get(currentPosition);
        Log.d("SelfAdaptingViewPager", "height=" + height);
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    //在切换tab的时候,重置ViewPager的高度  
    public void resetHeight(int currentPosition) {
        this.currentPosition = currentPosition;
        params = (MarginLayoutParams) getLayoutParams();
        if (params == null) {
            params = new MarginLayoutParams(LayoutParams.MATCH_PARENT, map.get(currentPosition));
        } else {
            params.height = map.get(currentPosition);
        }
        setLayoutParams(params);
    }
}

            但是我在用android4.4的机型测试时发现了问题,一个page留白,一个page不能完全展示,显然两个page所展示的高度正好弄反了。

       后来发现是和手机的android版本有关,使用android版本4.4及以下的机型都有这个问题。遍历viewpager的儿子,得到的第一个儿子是第二个page对应的view,得到的第二儿子是第一个page对应的view。

      这次周末在家我想再研究一下这个问题,结果自己写的demo在任何机型上并不会出现这样的问题。

      最终发现问题的出现和依赖的v7包有关系,我在工作项目中依赖的是com.android.support:appcompat-v7:23.4.0,demo中依赖的是com.android.support:appcompat-v7:23.1.1,所以可能是不同版本的v7包所包含的v4包中ViewPager对于getChildAt的实现有区别吧,以后有时间和基础了我想我会进一步研究的。

      下面是demo的截图:

      

      demo的代码地址:https://github.com/tingshuonitiao/AndroidStudy
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值