/XTableView

一个基于RecyclerView+Scroller实现的二维表格组件,同时支持侧滑菜单、拖动调整列表顺序等拓展功能。A two-dimensional table view, base on recyclerview, both support to side slide menu、drag item and more.

Primary LanguageJava

XTableView

一个基于RecyclerView+Scroller实现的二维表格组件,同时支持侧滑菜单、拖动调整列表顺序、刷新动画等拓展功能。
A two-dimensional table view, base on recyclerview, both support to side slide menu、drag item、refresh animation and more.

特性

  1. 基于RecyclerView实现,可复用视图
  2. 支持自定义数据源类型、表头及单元格样式
  3. 支持列表Item侧滑菜单
  4. 支持拖拽变换顺序
  5. 支持默认刷新动画
  6. 支持设置点击头部监听
  7. 支持AndroidX

效果预览

如何使用

在项目根目录的build.gradle添加:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

在项目的build.gradle添加如下依赖:

implementation 'com.github.GitHubZJY:XTableView:v1.0.0'

1.在xml中引用XTableView

<com.zjy.xtableview.XTableView
        android:id="@+id/table_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:swipeLayout="@layout/table_swipe_menu_layout"
        app:headerHeight="50dp"
        app:rowHeight="80dp"
        app:cellWidth="130dp"
        app:notifyAnim="true">

</com.zjy.xtableview.XTableView>

2.在代码中初始化XTableView

ITableView vTableView = findViewById(R.id.table_view);
//设置是否支持长按拖动列表项
vTableView.setLongPressDragEnable(true);
//设置是否支持侧滑菜单
vTableView.setSwipeEnable(true);

3.绑定数据

绑定数据的设计灵感来自于RecyclerView的adapter设计,与数据相关的操作均通过 XTableAdapter 作为中间者来进行.

1.自定义一个adapter继承于 XTableAdapter ,通过实现adapter的方法,自定义表格样式。XTableAdapter 的各个方法作用如下:

onBindTableHeader 绑定左上角表头视图
onBindColumnHeader 绑定(除表头外的)普通列头部视图
onCreateTableItem 创建每一个单元格的视图
onBindTableItem 绑定每一个单元格的视图数据
onCreateRowHeader 创建每一行的头部视图
onBindRowHeader 绑定每一行的头部视图数据

public class CustomTableAdapter extends XTableAdapter<String, TableRowModel<TableRowHeaderModel, TableRowCellModel>>{

    public CustomTableAdapter(Context context) {
        super(context);
    }

    @Override
    public View onBindTableHeader(String s) {
        TextView cellTv = new TextView(getContext());
        cellTv.setTextColor(getColor(R.color.table_view_second_txt_color));
        cellTv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13);
        cellTv.setGravity(Gravity.START|CENTER);
        cellTv.setText(s);
        return cellTv;
    }

    @Override
    public View onBindColumnHeader(int position, String t) {
        TextView cellTv = new TextView(getContext());
        cellTv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13);
        cellTv.setGravity(Gravity.CENTER);
        cellTv.setText(t);
        return cellTv;
    }

    @Override
    public View onCreateTableItem(int position) {
        View view = LayoutInflater.from(getContext()).inflate(R.layout.table_item_cell_layout, null);
        TextView cellTv = view.findViewById(R.id.cell_tv);
        cellTv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
        cellTv.setGravity(Gravity.CENTER);
        return view;
    }

    @Override
    public void onBindTableItem(int position, View view, TableRowModel<TableRowHeaderModel, TableRowCellModel> rowModel) {
        final TableRowCellModel cellModel = rowModel.getRowData().get(position);
        TextView cellTv = view.findViewById(R.id.cell_tv);
        cellTv.setTextColor(cellModel.isRise() ?
                getColor(R.color.table_view_rise_txt_color)
                : getColor(R.color.table_view_fall_txt_color));
        cellTv.setText(cellModel.getContent());
        cellTv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(getContext(), cellModel.getContent(), Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public View onCreateRowHeader(int position) {
        return LayoutInflater.from(getContext()).inflate(R.layout.table_item_title_layout, null);
    }

    @Override
    public void onBindRowHeader(int position, View view, TableRowModel<TableRowHeaderModel, TableRowCellModel> rowModel) {
        TextView vTitle = view.findViewById(R.id.title_tv);
        TextView vDetail = view.findViewById(R.id.detail_tv);
        String title = rowModel.rowHeader.getTitle();
        String detail = rowModel.rowHeader.getDetail();
        vTitle.setText(TextUtils.isEmpty(title) ? "" : title);
        vDetail.setText(TextUtils.isEmpty(detail) ? "" : detail);
    }
}

2.通过adapter的 bindData 绑定自定义数据源.

/**
 * 更新表格数据
 * @param header 左上角的表头数据
 * @param columnHeader 列头部数据集合
 * @param tableData 每一行的数据集合
 */
public void bindData(T header, List<T> columnHeader, List<H> tableData)

3.将adapter设置给XTableView.

vTableView.setTableAdapter(adapter);

 

4.数据变更时刷新视图.

数据变更也是通过adapter对象来进行:
如果是所有数据替换,可调用 bindData 方法设置新的数据,然后通过 notifyDataSetChanged 进行更新.
如果是单条数据刷新,可调用 notifyItemData(int position, H data) 进行更新,position是对应的下标,data为新的数据.
如果是单条数据插入,可调用 notifyInsertData(int position, H data) 进行更新,position是对应的下标,data为新的数据.  

5.设置监听回调

vTableView.setTableListener(new XTableListener() {
    @Override
    public void clickSwipeMenu(int position) {
        //点击菜单
        ...
    }

    @Override
    public void onItemMove(int fromPos, int toPos) {
        //拖拽Item
        ...
    }

    @Override
    public void onColumnHeaderItemClick(int position) {
        Toast.makeText(MainActivity.this, "点击了第" + position + "列的头部", Toast.LENGTH_SHORT).show();
        //点击某一列头部之后对列表数据进行重排序
        ..
    }
});

目前支持点击侧滑菜单、拖拽列表项、点击列头部的监听回调,例如实现根据某列进行排序的需求可以在 onColumnHeaderItemClick 里面进行  

6.其他属性.

本库也提供了LayoutManager的一些配置,例如: setReverseLayoutsetStackFromEndscrollToPositionscrollToPositionWithOffset 等,后续会再根据需要进行扩充.

 

感谢与参考

SwipeRecyclerView
侧滑和拖拽是在SwipeRecyclerView这个库的基础上修改,是一个基于RecyclerView拓展得不错的组件。本库的自定义样式和数据类型基于适配器的模式设计,后续会继续更新,提升组件的定制性和可拔插性,欢迎issue和star~