表格是自打我進公司之後就使用的控件,起初使用的是ScrollablePanel,從一開始的被花式吊打,到後期的熟練使用。 php
大佬寫的控件確實給個人工做帶來了極大的方便,不過仍是有些問題存在:java
在我深刻學習RecyclerView
之後,想能不能只用一層RecyclerView
,藉助LayoutManager
實現,寫着寫着,發現該思路可行,並實現了一款基於一個RecyclerView
的表格控件TableView
,先看一下效果:android
Github地址:github.com/mCyp/Orient…git
TableView具備以下特色:github
<?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中的主要函數: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_A
、Mode_C
和Mode_D
,須要再從新測量:
mTable.post(() -> mTable.reMeasure());
複製代碼
總的來講,TableView
的核心是TableLayoutManager
,也就是RecyclerView
中的LayoutManager
,相似於能夠隨時橫縱向切換的GridLayoutManager
,若是各位同窗對TableView
感興趣,我將會在後續的文章深刻原理。
探索不易,若是以爲【Orient-Ui】不錯,歡迎Star或者提出問題,年前的最後一篇技術文章啦,你們加油~
深刻原理以前,建議複習RecyclerView的原理:
《抽絲剝繭RecyclerView - 化整爲零》
《抽絲剝繭RecyclerView - LayoutManager》