美文网首页
ViewPager 设置wrap_content无效的问题

ViewPager 设置wrap_content无效的问题

作者: Showdy | 来源:发表于2020-04-23 15:48 被阅读0次
       @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            // For simple implementation, our internal size is always 0.
            // We depend on the container to specify the layout size of
            // our view.  We can't really know what it is since we will be
            // adding and removing different arbitrary views and do not
            // want the layout to change as this happens.
            setMeasuredDimension(getDefaultSize(0, widthMeasureSpec),
                    getDefaultSize(0, heightMeasureSpec));
        }
    

    在ViewPager的onMeasure()中直接调用getDefaultSize(), 而该方法在AT_MOST 和EXACTLY模式下,高度为match_parent, 所以在ViewPager中设置wrap_content会失效,默认为match_parent.

    public static int getDefaultSize(int size, int measureSpec) {
            int result = size;
            int specMode = MeasureSpec.getMode(measureSpec);
            int specSize = MeasureSpec.getSize(measureSpec);
    
            switch (specMode) {
            case MeasureSpec.UNSPECIFIED:
                result = size;
                break;
            case MeasureSpec.AT_MOST:
            case MeasureSpec.EXACTLY:
                result = specSize;
                break;
            }
            return result;
        }
    

    如何保证wrap_content 有效,可以去重写ViewPager的onMeasure() 方法,主动去测量子View的高度;

     @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            //所有子View高度的最大值
            int height = 0;
            //下面遍历所有child的高度
            for (int i = 0; i < getChildCount(); i++) {
                View child = getChildAt(i);
                //网络上的错误做法
                //child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
                ViewGroup.LayoutParams params = child.getLayoutParams();
                int childWidthMeaSpec = getChildMeasureSpec(widthMeasureSpec,
                        getPaddingLeft() + getPaddingRight(), params.width);
                int childHeightMeaSpec = getChildMeasureSpec(heightMeasureSpec,
                        getPaddingTop() + getPaddingBottom(), params.height);
                child.measure(childWidthMeaSpec, childHeightMeaSpec);
                int h = child.getMeasuredHeight();
                if (h > height) height = h; 
            }
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    

    最后需要注意的是,在构建Fragment请时使用inflate的三个参数的方法,即

      // 同样会导致高度失效
     inflater.inflate(R.layout.fragment_lazy,null)
     //正确使用
     inflater.inflate(R.layout.fragment_lazy,container,false)
    

    因为在inflate()方法中会根据设置root和attachToRoot两个值来构建LayoutParams, 使得设置的高度有效。

    public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
                       ....
                        ViewGroup.LayoutParams params = null;
                        if (root != null) {
                            if (DEBUG) {
                                System.out.println("Creating params from root: " +
                                        root);
                            }
                            // Create layout params that match root, if supplied
                            params = root.generateLayoutParams(attrs);
                            if (!attachToRoot) {
                                // Set the layout params for temp if we are not
                                // attaching. (If we are, we use addView, below)
                                temp.setLayoutParams(params);
                            }
                        }
                    .....
    }
    

    相关文章

      网友评论

          本文标题:ViewPager 设置wrap_content无效的问题

          本文链接:https://www.haomeiwen.com/subject/wfsaihtx.html