关于ViewPager的wrap_content无效的问题

本文深入探讨了Android中ViewPager的wrap_content问题,详细解析了ViewPager的onMeasure方法导致子View无法正确显示的原因,并提供了一种修改onMeasure方法来解决这一问题的有效方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

主要需要了解2个地方

你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。

ViewPager的onMeasure方法

ViewPager的onMeasure方法中直接设置死了宽高,所有都没有子View的事儿:

  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(getDefaultSize(0, widthMeasureSpec),
                getDefaultSize(0, heightMeasureSpec));
                ...

----------解决办法---------------

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int height = 0;
        //下面遍历所有child的高度
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            // 获取当前view的params的属性,
            // 这里要配合inflate(layout,parent,false),否则也是无效的
            LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();
            
            // 获取高度 与 mode
            final int heightMode;
            int childSpecSize;
            if (layoutParams.height >= 0) {
                heightMode = MeasureSpec.EXACTLY;
                childSpecSize = layoutParams.height;
            } else {
                childSpecSize = 0;
                heightMode = MeasureSpec.UNSPECIFIED;
            }
            // 开始进行测量view
            child.measure(widthMeasureSpec,
                    MeasureSpec.makeMeasureSpec(childSpecSize, heightMode));
            // 获取测量后view的高度
            int h = child.getMeasuredHeight();
            //采用最大的view的高度。
            if (h > height) {
                height = h;
            }
        }
        // 将最大的高度进行测量,然后得到的结果放到父类中
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(height,
                MeasureSpec.EXACTLY);
        // 最后在调用父类的方法,然后里面在执行 setMeasuredDimension
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
    

正常看下LinearLayout RelativeLayout的onMeasure()方法,都是遍历完所有的child然后才去调用这个方法setMeasuredDimension,而ViewPager却上来就直接调用这个方法;所以导致了child在加载到界面的时候是全屏显示

LayoutInflater.from(container.getContext()).inflate(layout,parent,false)

这个方法一般都会使用,但是我们在加载的时候就需要考虑后面的2个参数的含义;需要进入源码进行查看

            @Override
            public Object instantiateItem(@NonNull ViewGroup container, int position) {
				// 创建view对象的时候,3个参数都要进行添加
                View view = LayoutInflater.from(container.getContext())
                       .inflate(mList.get(position),container,false);
                container.addView(view);
                return view;
            }

----------------------------
 XmlResourceParser parser = res.getLayout(resource);
        try {
        // 看这个方法的内部
            return inflate(parser, root, attachToRoot);
        }
------------------------------
	...
	// 看到这个对象,里面可以拿到布局的宽高等信息
    ViewGroup.LayoutParams params = null;

                    if (root != null) {
                        // 创建出来
                        params = root.generateLayoutParams(attrs);
                        if (!attachToRoot) {
                            // 然后将创建的view设置对应的属性
                            temp.setLayoutParams(params);
                        }
                    }
	 ...

所以我们在调用inflate的时候需要将3个参数都进行传入,inflate(layout,container,false);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值