Flutter DataTable 看這一篇就夠了
- 2020 年 3 月 5 日
- 筆記

注意:無特殊說明,Flutter版本及Dart版本如下:Flutter版本: 1.12.13+hotfix.5 Dart版本: 2.7.0
DataTable
DataTable控件顯示錶格數據,DataTable需要設置行和列,用法如下:
DataTable( columns: [ DataColumn(label: Text('姓名')), DataColumn(label: Text('年齡')), ], rows: [ DataRow(cells: [ DataCell(Text('老孟')), DataCell(Text('18')), ]), ], )
columns
參數是DataTable的列,rows
參數是DataTable的每一行數據,效果如下:
在添加一行數據,只需要添加一個DataRow即可,用法如下:
DataTable( ... rows: [ DataRow(cells: [ DataCell(Text('老孟')), DataCell(Text('18')), ]), DataRow(cells: [ DataCell(Text('大黃')), DataCell(Text('20')), ]), ], )
在表頭顯示排序圖標:
DataTable( sortColumnIndex: 1, sortAscending: true, ... )
sortColumnIndex
參數表示表格顯示排序圖標的索引,sortAscending
參數表示升序或者降序,效果如下:

這裡要注意DataTable本身不能對數據進行排序,這些參數僅僅是外觀上的控制。
DataColumn
默認情況下數據是左對齊的,讓某一列右對齊只需設置DataColumn中numeric
參數true,設置如下:
DataTable( columns: [ DataColumn(label: Text('姓名')), DataColumn(label: Text('年齡'),numeric: true), ], ... )
效果:

設置DataColumn中tooltip
參數表示當長安此表頭時顯示提示,用法如下:
DataColumn(label: Text('姓名'),tooltip: '長按提示')
長按提示:

onSort
回調是用戶點擊表頭(DataColumn)時的回調,onSort
中第一個參數columnIndex
表示索引,ascending
參數表示升序或者降序,用法如下:
DataColumn(label: Text('年齡'), onSort: (int columnIndex, bool ascending){ //排序算法 }),
DataRow
可以顯示其中一行被選中,設置DataRow中selected
參數為true,用法如下:
DataRow( selected: true, ... )
效果如下:

onSelectChanged
參數是點擊每一行數據時的回調,用法如下:
DataRow( onSelectChanged: (selected){ } ... )
設置了onSelectChanged
參數,在數據的每一行和表頭的前面顯示勾選框,效果如下:

當然現在點擊還不能顯示選中的效果,增加選中效果,修改User model類,增加selected
屬性,表示當前行是否選中:
class User { User(this.name, this.age, {this.selected = false}); String name; int age; bool selected; }
修改數據:
List<User> data = [ User('老孟', 18), User('老孟1', 19,selected: true), User('老孟2', 20), User('老孟3', 21), User('老孟4', 22), ];
構建DataTable:
List<DataRow> dateRows = []; for (int i = 0; i < data.length; i++) { dateRows.add(DataRow( selected: data[i].selected, onSelectChanged: (selected){ setState(() { data[i].selected = selected; }); }, cells: [ DataCell(Text('${data[i].name}')), DataCell(Text('${data[i].age}')), ], )); } return DataTable(columns: [ DataColumn(label: Text('姓名')), DataColumn( label: Text('年齡'), ), ], rows: dateRows);
效果如下:

我們並沒有對錶頭的全選/取消全選勾選框進行控制,一個很大的疑問:點擊全選/取消全選勾選框,如果都勾選了,真實數據是否也發生變化了,對應本示例就是User中的selected
參數是否全部為true,可以肯定的告訴你User中的selected
參數已經全部變為true了,那是如何實現的呢?非常簡單,每一行的onSelectChanged
都被回調了一次。
DataCell
DataCell是DataRow中每一個子控件,DataCell子控件不一定是文本,也可以是圖標等任意組件,我們可以給DataCell設置編輯圖標:
DataCell(Text('name'),showEditIcon: true)
效果如下:

當然僅僅是一個圖標,placeholder
參數也是一樣的,設置為true,僅僅是文字的樣式變化了,onTap
為點擊回調,用法如下:
DataCell(Text('name'),showEditIcon: true,onTap: (){ print('DataCell onTap'); },placeholder: true)
效果如下:

排序
DateTable本身是沒有排序功能的,當用戶點擊表頭時對數據按照本列數據進行排序,用法如下,
數據model類:
class User { User(this.name, this.age); final String name; final int age; }
初始化數據及默認排序:
List<User> data = [ User('老孟', 18), User('老孟1', 19), User('老孟2', 20), User('老孟3', 21), User('老孟4', 22), ]; var _sortAscending = true;
構建DataTable:
DataTable( sortColumnIndex: 1, sortAscending: _sortAscending, columns: [ DataColumn(label: Text('姓名')), DataColumn(label: Text('年齡'), onSort: (int columnIndex, bool ascending){ setState(() { _sortAscending = ascending; if(ascending){ data.sort((a, b) => a.age.compareTo(b.age)); }else { data.sort((a, b) => b.age.compareTo(a.age)); } }); }), ], rows: data.map((user) { return DataRow(cells: [ DataCell(Text('${user.name}')), DataCell(Text('${user.age}')), ]); }).toList())
效果如下:

如果想給姓名
列也加上排序呢,修改如下:
var _sortAscending = true; var _sortColumnIndex =0; DataTable( sortColumnIndex: _sortColumnIndex, sortAscending: _sortAscending, columns: [ DataColumn(label: Text('姓名'),onSort: (int columnIndex, bool ascending){ setState(() { _sortColumnIndex = columnIndex; _sortAscending = ascending; if(ascending){ data.sort((a, b) => a.name.compareTo(b.name)); }else { data.sort((a, b) => b.name.compareTo(a.name)); } }); }), DataColumn(label: Text('年齡'), onSort: (int columnIndex, bool ascending){ setState(() { _sortColumnIndex = columnIndex; _sortAscending = ascending; if(ascending){ data.sort((a, b) => a.age.compareTo(b.age)); }else { data.sort((a, b) => b.age.compareTo(a.age)); } }); }), ], ... )
效果如下:

處理數據顯示不全問題
當表格列比較多的時候,可以使用SingleChildScrollView包裹DataTable,顯示不全時滾動顯示,用法如下:
List<DataRow> dateRows = []; for (int i = 0; i < data.length; i++) { dateRows.add(DataRow( cells: [ DataCell(Text('${data[i].name}')), DataCell(Text('${data[i].age}')), DataCell(Text('男')), DataCell(Text('2020')), DataCell(Text('10')), ], )); } return SingleChildScrollView( scrollDirection: Axis.horizontal, child: DataTable(columns: [ DataColumn(label: Text('姓名')), DataColumn( label: Text('年齡'), ), DataColumn( label: Text('性別'), ), DataColumn( label: Text('出生年份'), ), DataColumn( label: Text('出生月份'), ), ], rows: dateRows), );
效果如下:
