美文网首页UI效果仿写RecyclerView安卓开发相关
Orient-Ui | 单个RecyclerView实现花式表格

Orient-Ui | 单个RecyclerView实现花式表格

作者: 九心_ | 来源:发表于2020-01-13 09:56 被阅读0次

    前言

    表格是自打我进公司以后就使用的控件,起初使用的是ScrollablePanel,从一开始的被花式吊打,到后期的熟练使用。

    大佬写的控件确实给我的工作带来了极大的方便,不过还是有些问题存在:

    • 无法实现不规则的表格
    • 其核心是二层RecyclerView的嵌套,如果只用一层RecyclerView将会带来性能的提升
    • 多个RecyclerView有的时候会导致界面变形

    在我深入学习RecyclerView以后,想能不能只用一层RecyclerView,借助LayoutManager实现,写着写着,发现该思路可行,并实现了一款基于一个RecyclerView的表格控件TableView,先看一下效果:

    # 照片墙
    照片墙

    经常看到有同学问类似的首页如何实现,现在不用自定义View也可以轻松实现了哈~

    # 课程表
    课程表
    # 表格
    二维表格

    TableView具有如下特点:

    • 支持不规则表格
    • 同时支持横向和纵向滚动
    • 支持顶部和左侧悬浮
    • 基于RecyclerView,所以RecyclerView自定义子视图、高效回收、子视图多样性这些特点它都有
    • 没有多层RecyclerView嵌套,性能更棒

    Github地址:https://github.com/mCyp/Orient-Ui

    使用

    第一步 | 添加xml文件

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".ui.fragment.table.TableFragment">
    
        <com.orient.me.widget.rv.adapter.TableView
            android:id="@+id/tb"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    
    </FrameLayout>
    

    第二步 | 获取TableView

    在展示代码之前,了解一下TableView中的主要函数:

    方法 描述
    setTitle(boolean isLeftOpen, boolean isTopOpen) 左侧或者上侧的悬浮标题是否显示,默认显示
    setModeAndValue(int mode, int w, int h) mode-表格模式、w-具体的宽度\一行容纳的单元格数、h-具体的高度\一列容纳的单元格数

    这个setTitle(boolean isLeftOpen, boolean isTopOpen)有什么作用呢?为了确保表格的每一个单元格的长度和宽度都一样(子视图可以在横纵方向上占有多个单元格),宽和高都使用两种方式:

    • 设置具体的值,那么单元格的宽或者高的值就是具体的
    • 设置一行或者一列可以容纳的单元格数量

    所以宽高各有两种,模式的数量 = 2 * 2,总共有:

    Mode模式 w的说明 h的说明
    TableLayoutManager.MODE_A 父布局一行容纳的单元格数 父布局一列容纳的单元格数
    TableLayoutManager.MODE_B 单元格宽度 单元格高度
    TableLayoutManager.MODE_C 父布局一行容纳的单元格数 单元格高度
    TableLayoutManager.MODE_D 单元格宽度 父布局一列容纳的单元格数

    代码:

    // if use butterknife
    // or use findViewById
    @BindView(R.id.tb)
     TableView mTable;
    
    // 默认为 TableLayoutManager.MODE_A, 4, 8
    mTable.setModeAndValue(TableLayoutManager.MODE_A, 6, 8);
    

    第三步 | 创建数据类

    实现ICellItem接口:

    public class TableCell implements ICellItem {
    
        private String name;
        private String value;
        private int type;
        private int row;
        private int col;
        private int widthSpan;
        private int heightSpan;
    
        //... 省略构造函数和Get Set方法
    
        @Override
        public int getRow() {
            return row;
        }
    
        @Override
        public int getCol() {
            return col;
        }
    
        @Override
        public int getWidthSpan() {
            return widthSpan;
        }
    
        @Override
        public int getHeightSpan() {
            return heightSpan;
        }
    }
    

    第四步 | 设置适配器

    private TableAdapter<TableCell> mAdapter;
    
    protected void initWidget(View root) {
        // 假设在这个方法中初始化
        mTable.setAdapter(mAdapter = new TableAdapter<TableCell>(new ArrayList<>()) {
            @Override
            public int getItemLayout(TableCell tableCell, int pos) {
                // ... 返回子视图布局文件
                // 支持多类型
                return R.layout.table_cell_content_item;
            }
    
            @Override
            public BaseAdapter.ViewHolder<TableCell> onCreateViewHolder(View root, int itemType) {
                // itemType是子视图布局文件
                // 根据布局返回具体的ViewHolder
                return new ContentHolder(root);
            }
         });
    }
    
    // 具体的ViewHolder
    class ContentHolder extends BaseAdapter.ViewHolder<TableCell>{
    
            TextView mContent;
    
            public ContentHolder(View itemView) {
                super(itemView);
                mContent = itemView.findViewById(R.id.tv_name);
            }
    
            @Override
            protected void onBind(TableCell tableCell) {
                mContent.setText(tableCell.getValue());
            }
     }
    

    第五步 | 重新测绘

    如果TableView使用的模式是Mode_AMode_CMode_D,需要再重新测量:

    mTable.post(() -> mTable.reMeasure());
    

    总结

    总的来说,TableView的核心是TableLayoutManager,也就是RecyclerView中的LayoutManager,类似于可以随时横纵向切换的GridLayoutManager,如果各位同学对TableView感兴趣,我将会在后续的文章深入原理。

    年前的最后一篇技术文章啦,大家加油~

    深入原理之前,建议复习RecyclerView的原理:

    《抽丝剥茧RecyclerView - 化整为零》
    《抽丝剥茧RecyclerView - LayoutManager》

    相关文章

      网友评论

        本文标题:Orient-Ui | 单个RecyclerView实现花式表格

        本文链接:https://www.haomeiwen.com/subject/krywactx.html