天天看點

關于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方法就可以了,到這就差不多了。

剩下的就是在項目中,把控件都換成自定義的控件就好了。