Flutter之DataTable使用详解

简单闲聊

DataTable 这个名字在前端开发一定不陌生吧,与之同名的DataTable前端框架,大家都使用得很娴熟了,这个框架用于做为后台的数据展示跟操作,那么,在Flutter同样也是用于数据展示跟操作,Flutter里面怎么使用呢?让我们来一起学习吧!

1. DataTable参数

字段

类型

columns(表头)

List<DataColumn>

rows(内容行)

List<DataRow>

sortColumnIndex(排序列索引)

int

sortAscending(升序排序)

bool

onSelectAll(点击全选)

ValueSetter<bool>

2. DataColumn参数

字段

类型

label(标签,文本或者size=18的图标)

Widget

tooltip(工具提示)

String

numeric(是否包含数字)

bool

onSort(排序时调用)

DataColumnSortCallback

3. DataRow参数

字段

类型

selected(选中)

bool

onSelectChanged(点击选中改变)

ValueChanged<bool>

cells(子项)

List<DataCell>

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<Widget>

sortColumnIndex(排序列索引)

int

sortAscending(升序排序)

bool

onSelectAll(点击全选)

ValueSetter<bool>

initialFirstRowIndex (初始索引)

int

onPageChanged (页数更改监听,左右箭头)

ValueChanged<int>

rowsPerPage (默认一页显示的行数)

int

availableRowsPerPage (可选择页数)

List<int>

onRowsPerPageChanged (点击可选择页数下拉监听)

ValueChanged<int>

下面就是结合两个东西的了

  //默认的行数
  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将在近期更新一大波东西: 详情见:https://www.jianshu.com/p/da57f26c767f

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏deepcc

.clearfix:after的用法,清除浮动

2736
来自专栏菩提树下的杨过

Silverlight:利用Panel实现自定义布局

虽然Silverlight提供了几种基本的布局方式,比如Canvas,Grid,StackPanel,Border...,但有时候可能仍然会觉得不够用。 这时候...

2219
来自专栏小狼的世界

CSS3的过渡效果

在CSS2的世界中,过渡常常是非常单薄的,要么是从一种颜色变成另一种颜色、要么是从不透明变到透明,总而言之就是由一种状态变到另外一种状态。这就导致了很多页面给人...

1193
来自专栏码神联盟

碎片化 | 第四阶段-41-struts2字节流生成验证码-视频

如清晰度低,可转PC网页观看高清版本: http://v.qq.com/x/page/r056700jckx.html 验证码实现 需求: 在登录的页面,增...

2979
来自专栏前端菜鸟变老鸟

常见的html、css以及javascript兼容方案

    浏览器兼容性一直是一个前端开发人员不可避免的大问题,这篇文章主要列举了html、css以及javascript中一些常见的兼容性问题以及对应的解决方案。

971
来自专栏互联网开发者交流社区

FineUI控件集合

1657
来自专栏码农阿宇

利用GDI+在Winfrom绘制验证码

string yzm; private void yangzhengma() { Bitma...

3027
来自专栏Theo Tsao

Markdown语法

1022
来自专栏Google Dart

Flutte部件目录-基本部件(三) 顶

要显示snackbar或持久底部表,请通过Scaffold.of获取当前BuildContext的ScaffoldState,然后使用ScaffoldState...

2851
来自专栏iOS开发随笔

iOS去除导航栏和tabbar的1px横线

1524

扫码关注云+社区

领取腾讯云代金券