Orient-Ui | 單RecyclerView實現花式表格

前言

表格是自打我進公司之後就使用的控件,起初使用的是ScrollablePanel,從一開始的被花式吊打,到後期的熟練使用。 php

難

大佬寫的控件確實給個人工做帶來了極大的方便,不過仍是有些問題存在:java

  • 沒法實現不規則的表格
  • 其核心是二層RecyclerView的嵌套,若是隻用一層RecyclerView將會帶來性能的提高
  • 多個RecyclerView偶爾致使界面變形

在我深刻學習RecyclerView之後,想能不能只用一層RecyclerView,藉助LayoutManager實現,寫着寫着,發現該思路可行,並實現了一款基於一個RecyclerView的表格控件TableView,先看一下效果:android

# 照片牆

照片牆
常常看到有同窗問相似的首頁如何實現,如今不用自定義View也能夠輕鬆實現了哈~

# 課程表

課程表

# 表格

二維表格

Github地址:github.com/mCyp/Orient…git

特色

TableView具備以下特色:github

  • 支持不規則表格
  • 同時支持橫向和縱向滾動
  • 支持頂部和左側懸浮
  • 基於RecyclerView,因此RecyclerView自定義子視圖、高效回收、子視圖多樣性這些特色它都有
  • 摒棄多層RecyclerView嵌套,性能更棒

使用

第一步 | 添加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中的主要函數:ide

方法 描述
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 單元格寬度 父佈局一列容納的單元格數

代碼:post

// 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感興趣,我將會在後續的文章深刻原理。

探索不易,若是以爲【Orient-Ui】不錯,歡迎Star或者提出問題,年前的最後一篇技術文章啦,你們加油~

深刻原理以前,建議複習RecyclerView的原理:

《抽絲剝繭RecyclerView - 化整爲零》
《抽絲剝繭RecyclerView - LayoutManager》

相關文章
相關標籤/搜索