Android:RecyclerView跨行跨列的LayoutManager:Spannedgridlayoutmanager

前言: 

RecyclerView可以使用GridLayoutManager实现跨行,但是不能跨列;瀑布流布局可以跨列但是又不能跨行。原生自带的各个LayoutManager中并没有可以又跨行又能跨列的。网上搜寻了一番,找到了一个亲测可行好用的三方库:spannedgridlayoutmanager。

实现效果预览:

依赖库的地址:

GitHub:GitHub - jmartinesp/SpannedGridLayoutManager: Android RecyclerView.LayoutManager that resizes and reorders views based on SpanSize

gitee:SpannedGridLayoutManager: Android RecyclerView.LayoutManager that resizes and reorders views based on SpanSize (gitee.com)

使用:

1、添加依赖:

dependencies {
	implementation 'com.arasthel:spannedgridlayoutmanager:3.0.2'
}

如果依赖不成功或者想要自定义spannedgridlayoutmanager里面的代码,使用Module的方式来导入该项目。这边提供资源地址:spannedgridlayoutmanager-3.0.2资源-CSDN文库

2、代码中使用:

        recyclerView.setAdapter(adapter);
        //参数Orientation.VERTICAL表示列表竖向;4表示4列
        SpannedGridLayoutManager gridLayoutManager = new SpannedGridLayoutManager(
                SpannedGridLayoutManager.Orientation.VERTICAL, 4);
        gridLayoutManager.setSpanSizeLookup(new SpannedGridLayoutManager.SpanSizeLookup(position -> {
            int col = 1;
            int row = 1;
            switch (adapter.getItemViewType(position)) {
                case ITEM_TYPE_1x2:
                    col = 2;
                    break;
                case ITEM_TYPE_1x4:
                    col = 4;
                    break;
                case ITEM_TYPE_2x1:
                    row = 2;
                    break;
                case ITEM_TYPE_2x2:
                    col = 2;
                    row = 2;
                    break;
                case ITEM_TYPE_1x1:
                default:
                    break;
            }
            return new SpanSize(col, row);
        }));
        recyclerView.setLayoutManager(gridLayoutManager);

根据你每一项item所需要占的格子数大小设置所跨宽和列的单元格个数。

就可以啦。

完整代码:

这边代码包含了item拖动功能,详细解释和实现方式可以参考我另一篇博客:Android:RecyclerView自由拖动itemicon-default.png?t=N7T8http://t.csdnimg.cn/bPdbl不需要拖拽功能的忽略即可。

适配器:

public class AppsCardAdapter extends RecyclerView.Adapter<AppsCardAdapter.MyHolder> {
    private final List<Integer> mList;
    private final Context mContext;

    private final int ITEM_TYPE_1x1 = 0;
    private final int ITEM_TYPE_1x2 = 1;
    private final int ITEM_TYPE_1x4 = 2;
    private final int ITEM_TYPE_2x2 = 3;
    private final int ITEM_TYPE_2x1 = 4;

    AppsCardAdapter(Context context) {
        this.mContext = context;
        mList = new ArrayList<>();
    }

    @NonNull
    @Override
    public MyHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int itemType) {
        View rootView = LayoutInflater.from(mContext).inflate(
                R.layout.item_apps_card, viewGroup, false);
        return new MyHolder(rootView);
    }

    @SuppressLint("SetTextI18n")
    @Override
    public void onBindViewHolder(@NonNull MyHolder holder, int position) {
        int item = mList.get(position);
        holder.name.setText(item + "");
        holder.itemView.setOnClickListener(view -> {
            Toast.makeText(mContext, "item = "+item, Toast.LENGTH_SHORT).show();
        });
    }

    @Override
    public int getItemCount() {
        return mList.size();
    }

    @Override
    public int getItemViewType(int position) {
         TODO: 根据实际项目item的类型来,这边为了演示直接定死位置的类型了 
        switch (mList.get(position)){
            case 0:
                return ITEM_TYPE_1x4;
            case 1:
            case 4:
            case 6:
                return ITEM_TYPE_1x2;
            case 2:
            case 3:
                return ITEM_TYPE_2x1;
            case 5:
                return ITEM_TYPE_2x2;
            default:
                return ITEM_TYPE_1x1;
        }
    }

    static class MyHolder extends RecyclerView.ViewHolder {
        TextView name;

        public MyHolder(@NonNull  View itemView) {
            super(itemView);
            name = itemView.findViewById(R.id.name);
        }
    }

    //拖动功能的回调类
    private static class MyItemTouchHelperCallback extends ItemTouchHelper.Callback{

        private final AppsCardAdapter appsCardAdapter;
        public MyItemTouchHelperCallback(AppsCardAdapter appsCardAdapter) {
            this.appsCardAdapter = appsCardAdapter;
        }

        @Override
        public int getMovementFlags(@NonNull  RecyclerView recyclerView,
                                    @NonNull  RecyclerView.ViewHolder viewHolder) {
            if (viewHolder.getItemViewType() == appsCardAdapter.ITEM_TYPE_1x4) {
                //不可拖动
                return makeMovementFlags(0, 0);
            }
            final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN
                    | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
            return makeFlag(ItemTouchHelper.ACTION_STATE_DRAG, dragFlags);
        }

        @Override
        public boolean onMove(@NonNull  RecyclerView recyclerView,
                              @NonNull  RecyclerView.ViewHolder viewHolderSource,
                              @NonNull  RecyclerView.ViewHolder viewHolderTarget) {
            if (viewHolderTarget.getItemViewType() == appsCardAdapter.ITEM_TYPE_1x4) {
                //不可拖动到这里
                return false;
            }
            appsCardAdapter.onMove(viewHolderSource.getAdapterPosition(),
                    viewHolderTarget.getAdapterPosition());
            return true;
        }

        @Override
        public void onSwiped(@NonNull  RecyclerView.ViewHolder viewHolder, int i) {

        }
    }

    private void onMove(int sourcePosition, int targetPosition) {
        int item = mList.get(sourcePosition);
        mList.remove(sourcePosition);
        mList.add(targetPosition, item);
        notifyItemMoved(sourcePosition, targetPosition);
    }

    public void setRecyclerView(RecyclerView recyclerView) {
        recyclerView.setAdapter(this);
        SpannedGridLayoutManager gridLayoutManager = new SpannedGridLayoutManager(
                SpannedGridLayoutManager.Orientation.VERTICAL, 4);
        gridLayoutManager.setSpanSizeLookup(new SpannedGridLayoutManager.SpanSizeLookup(position -> {
            int col = 1;
            int row = 1;
            switch (getItemViewType(position)) {
                case ITEM_TYPE_1x2:
                    col = 2;
                    break;
                case ITEM_TYPE_1x4:
                    col = 4;
                    break;
                case ITEM_TYPE_2x1:
                    row = 2;
                    break;
                case ITEM_TYPE_2x2:
                    col = 2;
                    row = 2;
                    break;
                case ITEM_TYPE_1x1:
                default:
                    break;
            }
            return new SpanSize(col, row);
        }));
        recyclerView.setLayoutManager(gridLayoutManager);
        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(
                new MyItemTouchHelperCallback(this));
        itemTouchHelper.attachToRecyclerView(recyclerView);
    }

    public void setNewData(List<Integer> list) {
        this.mList.clear();
        this.mList.addAll(list);
        notifyDataSetChanged();
    }
}

Activity中使用:

        AppsCardAdapter adapter = new AppsCardAdapter(getContext());
        adapter.setRecyclerView(recyclerView);
        //测试数据
        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 0; i < 13; i++) {
            list.add(i);
        }
        adapter.setNewData(list);

完。

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值