天天看点

关于ScrollView嵌套ViewPager 嵌套 ListView 嵌套 WebView 大全

这几天做一个页面,需要用到ScrollView嵌套ViewPager,而ViewPager(Fragment)中又有两个Fragment 分别包含ListView以及WebView,大概的层级是这样的:

关于ScrollView嵌套ViewPager 嵌套 ListView 嵌套 WebView 大全

这样布局就会导致Viewpager WebView ListView 三个控件都显示不出来,导致这样的原因是,在Measure流程的时候,不能测出这三个控件的宽高,导致这三个控件不能显示,说到Measure 大家应该都知道该怎么解决了吧,没错,就是重写这三个控件的onMeasure方法,我们先来看看重写的ViewPager,当然重写ViewPager的方法,网上也有很多,就是关于这个问题的。大家,也可以去看看别人的博客,下面贴代码:

public class AutofitHeightViewPager extends ViewPager {
    private int current;
    private int height = ;
    /**
     * 保存position与对于的View
     */
    private HashMap<Integer, View> mChildrenViews = new LinkedHashMap<Integer, View>();

    private boolean scrollble = true;

    private static final String TAG = "AutofitHeightViewPager";

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

    public AutofitHeightViewPager(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(, 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) {

            RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
            if (layoutParams == null) {
                layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, height);
            } else {
                layoutParams.height = height;
            }

            Log.d(TAG, "resetHeight: "+height);

            setLayoutParams(layoutParams);
        }
    }
    /**
     * 保存position与对于的View
     */
    public void setObjectForPosition(View view, int position)
    {
        mChildrenViews.put(position, view);
    }
           

说好重写onMeasure 方法,怎么还多了两个方法呢?

如果只重写onMeasure方法,看看onMeasure方法,你会发现,在方法中,为了所Fragment都能显示完全,只会选择最大值,来作为ViewPager的总高度,那么,高度较小的那个Fragment下方就会留出很多空白,这样非常不美观,最好的办法就是动态设置当前ViewPager的高度。下面我们看看多出来的方法,是用来干嘛的。

setObjectForPosition:将当前的Fragment传递到类开头声明的成员中,建议在初始化Fragment的时候调用一下这个方法,将Fragment存入到当前的自定义的ViewPager中,以便后面使用,Position是查找对应Fragment的Key。

resetHeight:传入当前ViewPager显示的页面下标,获取到当前的Fragment的实际高度,设置为当前ViewPager的高度,这个方法建议设置ViewPager的页面切换监听,来实现设置不同高度。

当然,光重写ViewPager是不行的,还需要将 ViewPager 中对应加载的控件的onMeasure都重写,

ListView:

public class AutoFitHeightListView extends ListView {
    public AutoFitHeightListView(Context context) {
        super(context);
    }

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

    public AutoFitHeightListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int mExpandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> , MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, mExpandSpec);
    }
}
           

WebView:

public class AutoFitHeightWebView extends WebView {

    @SuppressLint("NewApi")
    public NoScrollWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public NoScrollWebView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

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

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int mExpandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> , MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, mExpandSpec);
    }

}
           

这两个就只要重写哦你Measure方法就可以了,到这就差不多了。

剩下的就是在项目中,把控件都换成自定义的控件就好了。