Flutter之DataTable使用詳解

rhyme_lph發表於2019-03-03

如需轉載,請尊重作者,註明出處,謝謝配合!

簡單閒聊

DataTable 這個名字在前端開發一定不陌生吧,與之同名的DataTable前端框架,大家都使用得很嫻熟了,這個框架用於做為後臺的資料展示跟操作,那麼,在Flutter同樣也是用於資料展示跟操作,Flutter裡面怎麼使用呢?讓我們來一起學習吧!

1. DataTable引數

欄位 型別
columns(表頭) List
rows(內容行) List
sortColumnIndex(排序列索引) int
sortAscending(升序排序) bool
onSelectAll(點選全選) ValueSetter

2. DataColumn引數

欄位 型別
label(標籤,文字或者size=18的圖示) Widget
tooltip(工具提示) String
numeric(是否包含數字) bool
onSort(排序時呼叫) DataColumnSortCallback

3. DataRow引數

欄位 型別
selected(選中) bool
onSelectChanged(點選選中改變) ValueChanged
cells(子項) List
index(索引DataRow.byIndex特有) int

4. DataCell引數

欄位 型別
child(子部件,一般為Text或DropdownButton) Widget
placeholder(是否為佔位符,若child為Text,顯示佔位符文字樣式) bool
showEditIcon(顯示編輯圖示,並非意義上的把child變為可編輯,需要結合onTap) bool
onTap(點選) VoidCallback

5.使用DataTableSource

新建一個Class繼承DataTableSource這個抽象類,實現4個方法

class MyTable extends DataTableSource{
  int _selectCount=0;//當前選中的行數
  @override
  DataRow getRow(int index) {
    //根據索引獲取內容行
  }
  @override//是否行數不確定
  bool get isRowCountApproximate => false;

  @override//有多少行
  int get rowCount => _shops.length;

  @override//選中的行數
  int get selectedRowCount => _selectCount;
}
複製程式碼

程式碼如上所示,現在table有了,那麼,我們還需要資料來源,我們一起弄一個商品庫存清單出來吧!

class Shop{
  final String name;
  final int number;
  final String type;
  final double price;
  bool selected=false;//預設為未選中
  Shop(this.name, this.number, this.type, this.price,);
}

  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,),
  ];
複製程式碼

合併在一起

class Shop {
  final String name;
  final int number;
  final String type;
  final double price;
  bool selected = false; //預設為未選中
  Shop(
    this.name,
    this.number,
    this.type,
    this.price,
  );
}

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; //當前選中的行數
  bool _isRowCountApproximate = false;//行數確定

  @override
  DataRow getRow(int index) {
    //根據索引獲取內容行
    if (index >= _shops.length || index < 0) throw FlutterError('兄弟,取錯資料了吧');
    //如果索引不在商品列表裡面,丟擲一個異常
    final Shop shop = _shops[index];
    return DataRow.byIndex(
        cells: <DataCell>[
          DataCell(Text(shop.name)),
          DataCell(Text('${shop.price}')),
          DataCell(Text('${shop.number}')),
          DataCell(Text(shop.type)),
        ],
        selected: shop.selected,
        index: index,
        onSelectChanged: (isSelected) {
          selectOne(index, isSelected);
        });
  }

  @override //是否行數不確定
  bool get isRowCountApproximate => _isRowCountApproximate;

  @override //有多少行
  int get rowCount => _shops.length;

  @override //選中的行數
  int get selectedRowCount => _selectCount;

  //選中單個
  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();
  }
}
複製程式碼

6.DataTableSource配合PaginatedDataTable

PaginatedDataTable

欄位 型別
header (表名,通常為Text,也可以是ButtonBar,FlatButton) Widget
actions (動作) List
sortColumnIndex(排序列索引) int
sortAscending(升序排序) bool
onSelectAll(點選全選) ValueSetter
initialFirstRowIndex (初始索引) int
onPageChanged (頁數更改監聽,左右箭頭) ValueChanged
rowsPerPage (預設一頁顯示的行數) int
availableRowsPerPage (可選擇頁數) List
onRowsPerPageChanged (點選可選擇頁數下拉監聽) ValueChanged

下面就是結合兩個東西的了

  //預設的行數
  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,
        ),
      );
}
複製程式碼

下面是一張圖片:

DataTable.gif

關注訂閱我,學習更多騷操作! flutter教程app將在近期更新一大波東西: 詳情見:flutter教程app

相關文章