Flutter DataTable 看這一篇就夠了

注意:無特殊說明,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),  );

效果如下:

今天的文章對大家是否有幫助?如果有,請在文章底部留言和點贊,以表示對我的支持,你們的留言、點贊和轉發關注是我持續更新的動力!