源碼:
1、實現 抽象類 DataTableSource 的幾個方法
-
DataRow getRow //獲取行數據
-
int get rowCount //獲取總行數
-
bool get isRowCountApproximate //數據源行數是否確定
-
int get selectedRowCount //獲取選中行數
-
selectOne //擴展單選功能
-
selectAll //擴展全選功能

import 'package:flutter/material.dart'; class MyTable extends DataTableSource { List<Shop> _shops = <Shop>[ Shop('小米6x', 100, '手機', 1699.0), Shop('華為P20', 50, '手機', 4999.0), Shop('華碩a61', 50, '電腦', 5700.0), Shop('iphone7plus耳機', 9999, '耳機', 60.0), Shop('iphone7plus256g', 1, '手機', 4760.0), Shop('金士頓8g內存條', 66, '內存條', 399.0), Shop('西門子洗衣機9.0kg', 890, '家電', 10399.0), Shop('三星66寸液晶智能電視', 800, '家電', 20389.0), ]; int _selectCount = 0; //當前選中的行數 int qty=0; bool _isRowCountApproximate = false;//行數確定 @override DataRow getRow(int index) { if (index>_shops.length|| index<0){FlutterError('數據錯誤!');} final Shop shop = _shops[index]; return DataRow.byIndex( index:index,cells: <DataCell>[ DataCell(Text(shop.name)), DataCell(Text('${shop.price}')), //數據加減功能 DataCell(Row( children: <Widget>[ IconButton(icon: Icon(Icons.arrow_left), onPressed: (){ shop.number+=1; notifyListeners(); }), Text('${shop.number}'), IconButton(icon: Icon(Icons.arrow_right), onPressed: (){ shop.number+=1; notifyListeners(); }), ], )), DataCell(Text(shop.type)), ], selected: shop.selected, onSelectChanged: (isselected){ selectOne(index,isselected); } ); } //選中單個 void selectOne(int index,bool isSelected){ Shop shop=_shops[index]; if (shop.selected != isSelected) { //如果選中就選中數量加一,否則減一 _selectCount = _selectCount += isSelected ? 1 : -1; shop.selected = isSelected; //更新 notifyListeners(); } } //選中全部 void selectAll(bool checked) { for (Shop _shop in _shops) { _shop.selected = checked; } _selectCount = checked ? _shops.length : 0; notifyListeners(); //通知監聽器去刷新 } //排序, void sort<T>(Comparable<T> getField(Shop shop),bool b){ _shops.sort((Shop s1,Shop s2){ if(!b){//兩個項進行交換 final Shop temp=s1; s1=s2; s2=temp; } final Comparable<T> s1Value=getField(s1); final Comparable<T> s2Value=getField(s2); return Comparable.compare(s1Value, s2Value); }); notifyListeners(); } @override int get rowCount=>_shops.length ; @override bool get isRowCountApproximate=>_isRowCountApproximate; @override int get selectedRowCount=>_selectCount; } class Shop{ final String name; int number; final String type; final double price; bool selected=false;//默認為未選中 Shop(this.name, this.number, this.type, this.price,); }
2、展示效果

import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bn_card/page/Widget/MyTable.dart'; class QueryPage extends StatefulWidget { @override QueryPageState createState() => new QueryPageState(); } class QueryPageState extends State<QueryPage> { static TextStyle Titlesty = TextStyle(color: Colors.red,fontSize: 18); static TextStyle bodyesty = TextStyle(); List<DataColumn> lcol= [ new DataColumn(label: Text('商品名',style: Titlesty,)), new DataColumn(label: Text('條碼',style: Titlesty,)), new DataColumn(label: Text('價格',style: Titlesty,)), new DataColumn(label: Text('數量',style: Titlesty,)), ]; List<DataRow> lrow= [ new DataRow(cells:[new DataCell(Text('香蕉')), DataCell(Text('10123')),DataCell(Text('12.8')),DataCell(Text('2')) ] ), new DataRow(cells:[new DataCell(Text('蘋果')), DataCell(Text('00123')),DataCell(Text('12.8')),DataCell(Text('2')) ] ), DataRow(cells:[new DataCell(Text('筆記本電腦',overflow: TextOverflow.ellipsis,)), DataCell(Container( child: Text('291267209960000005',overflow: TextOverflow.clip,softWrap: true,),),), DataCell(Text('1234567.8')),DataCell(Text('1'),onTap: (){ }) ] ), ]; //--------------------PaginatedDataTable------------------------------ //默認的行數 int _defalutRowPageCount = PaginatedDataTable.defaultRowsPerPage; int _sortColumnIndex; bool _sortAscending=true; MyTable table = MyTable(); //排序關聯_sortColumnIndex,_sortAscending void _sort<T>(Comparable<T> getField(Shop s),int index,bool b){ table.sort(getField, b); setState(() { this._sortColumnIndex=index; this._sortAscending=b; }); } List<DataColumn> getColumn() { return [ DataColumn(label: Text('商品名'),onSort: (i,b){_sort<String>((Shop p) =>p.name, i, b);}), DataColumn(label: Text('價格'),onSort: (i,b){_sort<num>((Shop p) =>p.price, i, b);}), DataColumn(label: Text('庫存'),onSort: (i,b){_sort<num>((Shop p) =>p.number, i, b);}), DataColumn(label: Text('類型'),onSort: (i,b){_sort<String>((Shop p) =>p.type, i, b);}), ]; } Widget getPaginatedDataTable(){ return SingleChildScrollView( child: PaginatedDataTable( rowsPerPage: _defalutRowPageCount, onRowsPerPageChanged: (value) { setState(() { _defalutRowPageCount = value; }); }, sortColumnIndex: _sortColumnIndex, initialFirstRowIndex: 0, sortAscending: _sortAscending, availableRowsPerPage: [ 5,10 ], onPageChanged: (value){ print('$value'); }, onSelectAll: table.selectAll, header: Text('商品庫存'), columns: getColumn(), source: table, ), ); } @override Widget build(BuildContext context) { return new Scaffold( body: Column( children: <Widget>[ DataTable(columns: lcol, rows: lrow, sortColumnIndex: 1, ), Expanded( child: getPaginatedDataTable(), ) ], ) ); } @override void initState() { // TODO: implement initState super.initState(); } @override void dispose() { // TODO: implement dispose super.dispose(); } @override void didUpdateWidget(QueryPage oldWidget) { // TODO: implement didUpdateWidget super.didUpdateWidget(oldWidget); } @override void didChangeDependencies() { // TODO: implement didChangeDependencies super.didChangeDependencies(); } }
3、界面圖: