RecyclerView和ScrollView嵌套

来源:互联网 发布:java io 编辑:程序博客网 时间:2024/05/21 03:24


我们的recyclerView有多个layoutmanager,通过重写layoutmanager的方法就可以让recyclerViewScrollView嵌套了。但是请注意,如果recyclerView很长那么强烈不建议去做嵌套,因为这样recyclerView会在展示的时候立刻展示所有内容,效率极低。

本文的两部分代码来自一个博主的博客,另一个是我自己写的,正好可以完全适用于现有的layoutmanager。大家需要的话可以试试,应该问题不大。

原博主的demohttps://github.com/Frank-Zhu/AndroidRecyclerViewDemo



1.LinearLayoutManagerScrollView嵌套


package com.frankzhu.recyclerviewdemo;


import android.content.Context;

import android.support.v7.widget.LinearLayoutManager;

import android.support.v7.widget.RecyclerView;

import android.util.Log;

import android.view.View;

import android.view.ViewGroup;


/**

 * Author:    ZhuWenWu

 * Version    V1.0

 * Date:      2015/2/26  14:15.

 * Description:

 * Modification  History:

 * Date             Author                Version            Description

 * -----------------------------------------------------------------------------------

 * 2015/2/26        ZhuWenWu            1.0                    1.0

 * Why & What is modified:

 */

public class FullyLinearLayoutManager extends LinearLayoutManager {


    private static final String TAG = FullyLinearLayoutManager.class.getSimpleName();


    public FullyLinearLayoutManager(Context context) {

        super(context);

    }


    public FullyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {

        super(context, orientation, reverseLayout);

    }


    private int[] mMeasuredDimension = new int[2];


    @Override

    public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,

                          int widthSpec, int heightSpec) {


        final int widthMode = View.MeasureSpec.getMode(widthSpec);

        final int heightMode = View.MeasureSpec.getMode(heightSpec);

        final int widthSize = View.MeasureSpec.getSize(widthSpec);

        final int heightSize = View.MeasureSpec.getSize(heightSpec);


        Log.i(TAG, "onMeasure called. \nwidthMode " + widthMode

                + " \nheightMode " + heightSpec

                + " \nwidthSize " + widthSize

                + " \nheightSize " + heightSize

                + " \ngetItemCount() " + getItemCount());


        int width = 0;

        int height = 0;

        for (int i = 0; i < getItemCount(); i++) {

            measureScrapChild(recycler, i,

                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),

                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),

                    mMeasuredDimension);


            if (getOrientation() == HORIZONTAL) {

                width = width + mMeasuredDimension[0];

                if (i == 0) {

                    height = mMeasuredDimension[1];

                }

            } else {

                height = height + mMeasuredDimension[1];

                if (i == 0) {

                    width = mMeasuredDimension[0];

                }

            }

        }

        switch (widthMode) {

            case View.MeasureSpec.EXACTLY:

                width = widthSize;

            case View.MeasureSpec.AT_MOST:

            case View.MeasureSpec.UNSPECIFIED:

        }


        switch (heightMode) {

            case View.MeasureSpec.EXACTLY:

                height = heightSize;

            case View.MeasureSpec.AT_MOST:

            case View.MeasureSpec.UNSPECIFIED:

        }


        setMeasuredDimension(width, height);

    }


    private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,

                                   int heightSpec, int[] measuredDimension) {

        try {

            View view = recycler.getViewForPosition(0);//fix动态添加时报IndexOutOfBoundsException


            if (view != null) {

                RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();


                int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,

                        getPaddingLeft() + getPaddingRight(), p.width);


                int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,

                        getPaddingTop() + getPaddingBottom(), p.height);


                view.measure(childWidthSpec, childHeightSpec);

                measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;

                measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;

                recycler.recycleView(view);

            }

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

        }

    }

}


 

2.GridLayoutManagerScrollView进行嵌套

 


package com.frankzhu.recyclerviewdemo;


import android.content.Context;

import android.support.v7.widget.GridLayoutManager;

import android.support.v7.widget.RecyclerView;

import android.view.View;

import android.view.ViewGroup;


/**

 * Author:    ZhuWenWu

 * Version    V1.0

 * Date:      2015/2/26  14:14.

 * Description:

 * Modification  History:

 * Date             Author                Version            Description

 * -----------------------------------------------------------------------------------

 * 2015/2/26        ZhuWenWu            1.0                    1.0

 * Why & What is modified:

 */

public class FullyGridLayoutManager extends GridLayoutManager {

    public FullyGridLayoutManager(Context context, int spanCount) {

        super(context, spanCount);

    }


    public FullyGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {

        super(context, spanCount, orientation, reverseLayout);

    }


    private int[] mMeasuredDimension = new int[2];


    @Override

    public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {

        final int widthMode = View.MeasureSpec.getMode(widthSpec);

        final int heightMode = View.MeasureSpec.getMode(heightSpec);

        final int widthSize = View.MeasureSpec.getSize(widthSpec);

        final int heightSize = View.MeasureSpec.getSize(heightSpec);


        int width = 0;

        int height = 0;

        int count = getItemCount();

        int span = getSpanCount();

        for (int i = 0; i < count; i++) {

            measureScrapChild(recycler, i,

                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),

                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),

                    mMeasuredDimension);


            if (getOrientation() == HORIZONTAL) {

                if (i % span == 0) {

                    width = width + mMeasuredDimension[0];

                }

                if (i == 0) {

                    height = mMeasuredDimension[1];

                }

            } else {

                if (i % span == 0) {

                    height = height + mMeasuredDimension[1];

                }

                if (i == 0) {

                    width = mMeasuredDimension[0];

                }

            }

        }


        switch (widthMode) {

            case View.MeasureSpec.EXACTLY:

                width = widthSize;

            case View.MeasureSpec.AT_MOST:

            case View.MeasureSpec.UNSPECIFIED:

        }


        switch (heightMode) {

            case View.MeasureSpec.EXACTLY:

                height = heightSize;

            case View.MeasureSpec.AT_MOST:

            case View.MeasureSpec.UNSPECIFIED:

        }


        setMeasuredDimension(width, height);

    }


    private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,

                                   int heightSpec, int[] measuredDimension) {

        if (position < getItemCount()) {

            try {

                View view = recycler.getViewForPosition(0);//fix动态添加时报IndexOutOfBoundsException

                if (view != null) {

                    RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();

                    int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,

                            getPaddingLeft() + getPaddingRight(), p.width);

                    int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,

                            getPaddingTop() + getPaddingBottom(), p.height);

                    view.measure(childWidthSpec, childHeightSpec);

                    measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;

                    measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;

                    recycler.recycleView(view);

                }

            } catch (Exception e) {

                e.printStackTrace();

            }

        }

    }

}


 

 

 

3.StaggeredGridLayoutManagerScrollView进行嵌套


package com.kale.waterfalldemo.extra.RecyclerView;


import android.support.v7.widget.RecyclerView;

import android.support.v7.widget.StaggeredGridLayoutManager;

import android.view.View;

import android.view.ViewGroup;


/**

 * @author Jack Tony

 * @brief 不规则排列(类似于瀑布流)的布局管理器

 * @date 2015/4/6

 */

public class ExStaggeredGridLayoutManager extends StaggeredGridLayoutManager {


    public ExStaggeredGridLayoutManager(int spanCount, int orientation) {

        super(spanCount, orientation);

    }


    // 尺寸的数组,[0]是宽,[1]是高

    private int[] measuredDimension = new int[2];


    // 用来比较同行/列那个item罪宽/

    private int[] dimension;



    @Override


    public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {

        // 宽的mode+size

        final int widthMode = View.MeasureSpec.getMode(widthSpec);

        final int widthSize = View.MeasureSpec.getSize(widthSpec);

        // 高的mode + size

        final int heightMode = View.MeasureSpec.getMode(heightSpec);

        final int heightSize = View.MeasureSpec.getSize(heightSpec);


        // 自身宽高的初始值

        int width = 0;

        int height = 0;

        // item的数目

        int count = getItemCount();

        // item的列数

        int span = getSpanCount();

        // 根据行数或列数来创建数组

        dimension = new int[span];


        for (int i = 0; i < count; i++) {

            measureScrapChild(recycler, i,

                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),

                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), measuredDimension);


           // 如果是竖直的列表,计算item的高,否则计算宽度

            //Log.d("LISTENER", "position " + i + " height = " + measuredDimension[1]);

            if (getOrientation() == VERTICAL) {

                dimension[findMinIndex(dimension)] += measuredDimension[1];

            } else {

                dimension[findMinIndex(dimension)] += measuredDimension[0];

            }

        }

        if (getOrientation() == VERTICAL) {

            height = findMax(dimension);

        } else {

            width = findMax(dimension);

        }

        


        switch (widthMode) {

            // 当控件宽是match_parent时,宽度就是父控件的宽度

            case View.MeasureSpec.EXACTLY:

                width = widthSize;

                break;

            case View.MeasureSpec.AT_MOST:

                break;

            case View.MeasureSpec.UNSPECIFIED:

                break;

        }

        switch (heightMode) {

            // 当控件高是match_parent时,高度就是父控件的高度

            case View.MeasureSpec.EXACTLY:

                height = heightSize;

                break;

            case View.MeasureSpec.AT_MOST:

                break;

            case View.MeasureSpec.UNSPECIFIED:

                break;

        }

        // 设置测量尺寸  

        setMeasuredDimension(width, height);

    }


    private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,

            int heightSpec, int[] measuredDimension) {


        // 挨个遍历所有item

        if (position < getItemCount()) {

            try {

                View view = recycler.getViewForPosition(position);//fix动态添加时报IndexOutOfBoundsException


                if (view != null) {

                    RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) view.getLayoutParams();

                    int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec, getPaddingLeft() + getPaddingRight(), lp.width);

                    int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec, getPaddingTop() + getPaddingBottom(), lp.height);

                    // view进行测量,然后可以通过getMeasuredWidth()获得测量的宽,高类似

                    view.measure(childWidthSpec, childHeightSpec);

                    // item的宽高放入数组中

                    measuredDimension[0] = view.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;

                    measuredDimension[1] = view.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;

                    recycler.recycleView(view);

                }

            } catch (Exception e) {

                e.printStackTrace();

            }

        }

    }


    private int findMax(int[] array) {

        int max = array[0];

        for (int value : array) {

            if (value > max) {

                max = value;

            }

        }

        return max;

    }


    /**

     * 得到最数组中最小元素的下标

     *

     * @param array

     * @return

     */

    private int findMinIndex(int[] array) {

        int index = 0;

        int min = array[0];

        for (int i = 0; i < array.length; i++) {

            if (array[i] < min) {

                min = array[i];

                index = i;

            }

        }

        return index;

    }

   

}


 

0 0
原创粉丝点击