RecycleView实现夸行或者跨列

项目需要实现一个柜格列表,主柜会应为硬件型号不同,某个item会有夸行效果.这边记录下.
实现效果

1. 自定义GridLayoutManager

GridLayoutManager网格布局可以设置item的spanSize,从而实现跨行或者跨列.

/**
 * recycleView
 * 1.方向为HORIZONTAL实现跨行, addItemDecoration()实现水平方向间隔,垂直方向间隔要单独处理.
 * 2.方向为VERTICAL 实现跨列 ,addItemDecoration()实现垂直方向间隔,水平方向间隔要单独处理.
 */
public class CustomGridLayoutManager extends GridLayoutManager {
    // 间隔 单方向
    private final int spacing;
    private static final String TAG = "SpanGridLayoutManager";
    // 计算的列数
    private int cachedColumnCount = -1;
    // 计算的行数
    private int cachedRowCount = -1;

    /**
     * @param context     .
     * @param spanCount   HORIZONTAL:显示几行   VERTICAL:显示几列
     * @param orientation .方向
     * @param spacing     .
     * @param data        map 跨行/跨列     key=position   value=spanSize.
     */
    public CustomGridLayoutManager(Context context, int spanCount, int orientation, int spacing, Map<Integer, Integer> data) {
        super(context, spanCount, orientation, false);
        this.spacing = spacing;

        if (data != null && !data.isEmpty()) {
            Set<Integer> keys = data.keySet();
            setSpanSizeLookup(new SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    int spanSize = 1;
                    for (Integer key : keys) {
                        if (position == key)
                            spanSize = data.getOrDefault(key, 1);
                    }
                    return spanSize;
                }
            });
        }
    }

    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        super.onLayoutChildren(recycler, state);

        int spanCount = getSpanCount();
        int totalSpacing = spanCount * spacing;
        int itemCount = state.getItemCount();

        if (getOrientation() == RecyclerView.HORIZONTAL) {
            // RecyclerView.HORIZONTAL  纵向跨行
            int cellHeight = (getHeight() - totalSpacing) / spanCount;

            if (cachedColumnCount == -1) {
                cachedColumnCount = calculateRowOrColumnCount(itemCount, spanCount);
            }
          //  int columnCount = cachedColumnCount;
          //  if (columnCount <= 0) return;
            if (cachedColumnCount <= 0) return;

            int totalWidthSpacing = cachedColumnCount * spacing;
            int cellWidth = (getWidth() - totalWidthSpacing) / cachedColumnCount;
            Log.i(TAG, "onLayoutChildren: w= " + getWidth() + "-----h = " + getHeight() + "=== spanCount = " + spanCount);
            for (int i = 0; i < getChildCount(); i++) {
                View view = getChildAt(i);
                if (view != null) {
                    int position = getPosition(view);
                    int spanSize = getSpanSizeLookup().getSpanSize(position);
                    RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams();

                    int newHeight;
                    if (spanSize > 1) {
                        newHeight = cellHeight * spanSize + (spanSize - 1) * spacing;
                    } else {
                        newHeight = cellHeight;
                    }

                    if (params.height != newHeight || params.width != cellWidth) {
                        params.height = newHeight;
                        params.width = cellWidth;
                        view.setLayoutParams(params);
                    }
                }
            }
        } else {
            // RecyclerView.VERTICAL  横向跨列
            int cellWidth = (getWidth() - totalSpacing) / spanCount;

            if (cachedRowCount == -1) {
                cachedRowCount = calculateRowOrColumnCount(itemCount, spanCount);
            }
           // int rowCount = cachedRowCount;
            //if (rowCount <= 0) return;
            if (cachedRowCount <= 0) return;

            int totalHeightSpacing = cachedRowCount * spacing;
            int cellHeight = (getHeight() - totalHeightSpacing) / cachedRowCount;

            for (int i = 0; i < getChildCount(); i++) {
                View view = getChildAt(i);
                if (view != null) {
                    int position = getPosition(view);
                    int spanSize = getSpanSizeLookup().getSpanSize(position);
                    RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams();

                    int newWidth;
                    if (spanSize > 1) {
                        newWidth = cellWidth * spanSize + (spanSize - 1) * spacing;
                    } else {
                        newWidth = cellWidth;
                    }

                    if (params.height != cellHeight || params.width != newWidth) {
                        params.height = cellHeight;
                        params.width = newWidth;
                        view.setLayoutParams(params);
                    }
                }
            }
        }
    }


    /**
     * 计算行数或列数
     *
     * @param itemCount recycleView item总数量
     * @param spanCount = 5  ,HORIZONTAL:代表5行   VERTICAL:代表5列
     * @return 行数或列数
     */
    private int calculateRowOrColumnCount(int itemCount, int spanCount) {
        int count = 0;
        for (int i = 0; i < itemCount; i++) {
            int spanSize = getSpanSizeLookup().getSpanSize(i);
            if (spanSize > 1) {
                count += spanSize - 1;
            }
        }
        return (int) Math.ceil((double) (itemCount + count) / spanCount);
    }
}

2. 使用
CustomGridLayoutManager 构造的data集合可以添加多个item的position,并设置对应的spanSize 
  • 设置LinearLayoutManager.VERTICAL item跨列
  • 设置LinearLayoutManager.HORIZONTALitem跨行
		List<String> list = new ArrayList<>();
        for (int i = 0; i < 18; i++) {
            list.add((i + 1) + "");
        }

        MyAdapter myAdapter = new MyAdapter(list);
        viewBinging.recycleview.setAdapter(myAdapter);
        Map<Integer, Integer> data = new HashMap<>();
        data.put(0, 2);
        data.put(7, 2);

        CustomGridLayoutManager layoutManager = new CustomGridLayoutManager(mContext, 4,
                LinearLayoutManager.VERTICAL, 10, data);

        viewBinging.recycleview.setLayoutManager(layoutManager);
        viewBinging.recycleview.addItemDecoration(new SpacingItemDecoration(10));
        //viewBinging.recycleview.setOverScrollMode(View.OVER_SCROLL_NEVER);

end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值