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、代码中使用:

java 复制代码
        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自由拖动itemhttp://t.csdnimg.cn/bPdbl不需要拖拽功能的忽略即可。

适配器:

java 复制代码
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中使用:

java 复制代码
        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);

完。

相关推荐
邪修king6 分钟前
Re:Linux 系统篇(三十四):进程间通信开篇Chapter1 —— 匿名管道 pipe 深度拆解与代码实战
android·linux·运维·开发语言
AFinalStone15 分钟前
Android7 SystemUI 源码解析(一)全景概览与架构设计
android·systemui
2501_916008891 小时前
如何实现iOS App代码混淆:SwiftShield使用指南
android·ios·小程序·https·uni-app·iphone·webview
恋猫de小郭1 小时前
AndroidX 新增 Security State ,支持可编程的系统安全状态查询
android·前端·flutter
AFinalStone2 小时前
Android7 SystemUI 源码解析(六)QuickSettings快捷设置面板
android·systemui
Kapaseker2 小时前
你有搞明白 Volatile 什么意思吗?
android·kotlin
美狐美颜SDK开放平台2 小时前
直播APP源码与视频美颜sdk如何配合?一套完整开发思路
android·人工智能·计算机视觉·音视频·直播美颜sdk
心平气和量大福大2 小时前
android-权限
android·java
2501_916008893 小时前
怎么用 Godot 导出 iOS 应用并上架 App Store?签名字段该填什么?
android·ios·小程序·https·uni-app·iphone·webview
智慧物业老杨5 小时前
物业日常巡查的数智化重构:从“打卡式巡检“到“闭环式风控“
android·java·人工智能·系统架构·rxjava