ViewPager 设置wrap_content无效的问题

   @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无效的问题)