飞道的博客

Android LayoutManager高端玩家,实现花式表格!

483人阅读  评论(0)

如果你对RecyclerView原理还不是特别了解,非常建议你读一下。

本文的项目也是学习自定义LayoutManager绝佳资料,大家有需要的可以好好拜读。

前言

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

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

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

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

照片墙

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

课程表

表格

TableView具有如下特点:

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

Github地址

使用

第一步 | 添加xml文件


  
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools= "http://schemas.android.com/tools"
  4. android:layout_width= "match_parent"
  5. android:layout_height= "match_parent"
  6. tools:context= ".ui.fragment.table.TableFragment">
  7. <com.orient.me.widget.rv.adapter.TableView
  8. android:id= "@+id/tb"
  9. android:layout_width= "match_parent"
  10. android:layout_height= "match_parent"/>
  11. </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 单元格宽度 父布局一列容纳的单元格数

代码:


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

第三步 | 创建数据类

实现ICellItem接口:


  
  1. public class TableCell implements ICellItem {
  2. private String name;
  3. private String value;
  4. private int type;
  5. private int row;
  6. private int col;
  7. private int widthSpan;
  8. private int heightSpan;
  9. //... 省略构造函数和Get Set方法
  10. @Override
  11. public int getRow() {
  12. return row;
  13. }
  14. @Override
  15. public int getCol() {
  16. return col;
  17. }
  18. @Override
  19. public int getWidthSpan() {
  20. return widthSpan;
  21. }
  22. @Override
  23. public int getHeightSpan() {
  24. return heightSpan;
  25. }
  26. }

第四步 | 设置适配器


  
  1. private TableAdapter<TableCell> mAdapter;
  2. protected void initWidget(View root) {
  3. // 假设在这个方法中初始化
  4. mTable.setAdapter(mAdapter = new TableAdapter<TableCell>( new ArrayList<>()) {
  5. @Override
  6. public int getItemLayout(TableCell tableCell, int pos) {
  7. // ... 返回子视图布局文件
  8. // 支持多类型
  9. return R.layout.table_cell_content_item;
  10. }
  11. @Override
  12. public BaseAdapter. ViewHolder<TableCell> onCreateViewHolder(View root, int itemType) {
  13. // itemType是子视图布局文件
  14. // 根据布局返回具体的ViewHolder
  15. return new ContentHolder(root);
  16. }
  17. });
  18. }
  19. // 具体的ViewHolder
  20. class ContentHolder extends BaseAdapter.ViewHolder<TableCell>{
  21. TextView mContent;
  22. public ContentHolder(View itemView) {
  23. super(itemView);
  24. mContent = itemView.findViewById(R.id.tv_name);
  25. }
  26. @Override
  27. protected void onBind(TableCell tableCell) {
  28. mContent.setText(tableCell.getValue());
  29. }
  30. }

第五步 | 重新测绘

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

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

总结

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

最后对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!

最后这里是关于我自己的Android 学习,面试文档,视频收集大整理,有兴趣的伙伴们可以看看~


转载:https://blog.csdn.net/weixin_44339238/article/details/104200894
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场