持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情
前言:
DataTable 这个名字在大前端开发一定不陌生吧,与之同名的DataTable前端框架,大家都使用得很娴熟了,这个框架用于做为后台的数据展示跟操作,那么,在Flutter同样也是用于数据展示跟操作,Flutter里面怎么使用呢?让我们来一起学习吧!
1.DataTable介绍
数据表显示表格数据,需要设置行和列
2.DataTable属性
| 属性 | 介绍 |
|---|---|
| columns | @required 列数组 |
| sortColumnIndex | 有排列箭头的列,仅仅是展示箭头 |
| sortAscending | 是否升序,默认为 true, 排列顺序,仅仅是箭头向上还是向下 |
| onSelectAll | 左上角全选按钮点击回调 |
| dataRowHeight | Rows 中每条 Row 高度,默认为 kMinInteractiveDimension = 48.0 |
| headingRowHeight | 顶部 Row 高度,默认为 56.0 |
| horizontalMargin | 左侧边距,默认为 24.0 |
| columnSpacing | 每一列间距,默认为 56.0 |
| showCheckboxColumn | 是否展示左侧 checkbox 这一列,默认为 true |
| dividerThickness | 分割线宽度,默认为 1.0 |
| rows | @required 行数组 |
3.DataColumn属性
| 属性 | 介绍 |
|---|---|
| label | 文本 |
| tooltip | 长按提示 |
| numeric | 是否居右,默认为 false |
| onSort | 点击排序箭头回调函数 |
4.DataRow属性
| 属性 | 介绍 |
|---|---|
| selected | checkbox 是否选中,默认为 false |
| onSelectChanged | 左侧 checkbox 点击事件 |
| color | DataRow 颜色回调函数 |
| cells | 数组 |
5.DataCell属性
| 属性 | 介绍 |
|---|---|
| child | 子组件 |
| placeholder | 是否为 placeholder,会改变 Text 样式 |
| showEditIcon | 是否展示编辑按钮 |
| onTap | 点击事件 |
6.DataTable基本用法
-
一个基础的DataTable需要设置columns列,rows行
-
由于DataTable本身是不具备滑动属性,所以当数据比较多的时候需要嵌套滑动组件,使用两个SingleChildScrollView来完成纵向横向的滑动
代码案例:
/**
* @Author wywinstonwy
* @Date 2021/12/28 9:45 下午
* @Description:
*/
import 'package:demo202112/utils/common_appbar.dart';
import 'package:flutter/material.dart';
class WyDataTable extends StatefulWidget {
const WyDataTable({Key? key}) : super(key: key);
@override
_WyDataTableState createState() => _WyDataTableState();
}
class _WyDataTableState extends State<WyDataTable> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: getAppBar('DataTable'),
body: _baseDataTable(),
);
}
_baseDataTable(){
return DataTable(
columns: [
DataColumn(label: Text('姓名')),
DataColumn(label: Text('年龄')),
],
rows: [
DataRow(cells: [
DataCell(Text('老王')),
DataCell(Text('26')),
]),
DataRow(cells: [
DataCell(Text('老李')),
DataCell(Text('16')),
]),
DataRow(cells: [
DataCell(Text('老李')),
DataCell(Text('16')),
]),
],
);
}
}
运行效果:
在表头显示排序图标:
DataTable(
sortColumnIndex: 1,
sortAscending: true,
...
)
sortColumnIndex参数表示表格显示排序图标的索引,sortAscending参数表示升序或者降序,效果如下:
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> dataRows = [];
for(int i=0;i<data.length;i++){
dataRows.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: dataRows);
}
运行效果:
我们并没有对表头的全选/取消全选勾选框进行控制,一个很大的疑问:点击全选/取消全选勾选框,如果都勾选了,真实数据是否也发生变化了,对应本示例就是User中的selected参数是否全部为true,可以肯定的告诉你User中的selected参数已经全部变为true了,那是如何实现的呢?非常简单,每一行的onSelectChanged都被回调了一次。
DataCell
DataCell是DataRow中每一个子控件,DataCell子控件不一定是文本,也可以是图标等任意组件,我们可以给DataCell设置编辑图标:
DataCell(Text('${data[i].age}'),showEditIcon: true),
运行效果:
当然仅仅是一个图标,placeholder参数也是一样的,设置为true,仅仅是文字的样式变化了,onTap为点击回调,用法如下:
DataCell(Text('${data[i].age}'),showEditIcon: true,onTap: (){
print('${data[i].age}');
},placeholder: true),
排序
DateTable本身是没有排序功能的,当用户点击表头时对数据按照本列数据进行排序,用法如下,
数据model类:
/**
* @Author wywinstonwy
* @Date 2021/12/28 9:45 下午
* @Description:
*/
import 'package:demo202112/utils/common_appbar.dart';
import 'package:flutter/material.dart';
class WyDataTable extends StatefulWidget {
const WyDataTable({Key? key}) : super(key: key);
@override
_WyDataTableState createState() => _WyDataTableState();
}
class _WyDataTableState extends State<WyDataTable> {
List<User> data = [
User('老往', 18),
User('老李1', 19,selected: true),
User('老张2', 20),
User('老舍3', 21),
User('老牛4', 22),
];
var _sortAscending = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: getAppBar('DataTable'),
body: _buildDataRows(),
);
}
_baseDataTable(){
return DataTable(
sortColumnIndex: 1,
sortAscending: true,
columns: [
DataColumn(label: Text('姓名'),tooltip: '长按提示'),
DataColumn(label: Text('年龄'),numeric: true,onSort: (int columnIndex,bool ascending){
//排序算法
}),
],
rows: [
DataRow(cells: [
DataCell(Text('老王')),
DataCell(Text('26')),
]),
DataRow(
selected: true,
onSelectChanged: (selected){
print(selected);
},
cells: [
DataCell(Text('老李')),
DataCell(Text('16')),
]),
DataRow(cells: [
DataCell(Text('老李')),
DataCell(Text('16')),
]),
],
);
}
_buildDataRows(){
List<DataRow> dataRows = [];
for(int i=0;i<data.length;i++){
dataRows.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(
sortColumnIndex: 1,
sortAscending: true,
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: dataRows);
}
}
class User {
User(this.name, this.age, {this.selected = false});
String name;
int age;
bool selected;
}
运行效果:
处理数据显示不全问题
当表格列比较多的时候,可以使用SingleChildScrollView包裹DataTable,显示不全时滚动显示,用法如下:
_buildDataRows(){
List<DataRow> dataRows = [];
for(int i=0;i<data.length;i++){
dataRows.add(DataRow(
selected: data[i].selected,
onSelectChanged: (selected){
setState(() {
data[i].selected = selected!;
});
},
cells: [
DataCell(Text('${data[i].name}')),
DataCell(Text('${data[i].age}'),),
DataCell(Text('${data[i].address}'),),
DataCell(Text('${data[i].birthday}'),),
DataCell(Text('${data[i].birthday1}'),),
]));
}
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
sortColumnIndex: 1,
sortAscending: true,
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));
}
});
}),
DataColumn(label: Text('地址')),
DataColumn(label: Text('出身日期')),
DataColumn(label: Text('出身日期')),
],
rows: dataRows),
);
}
运行效果:
第三方组件
除了flutter系统提供的以外,可以参考pub.dev第三方组件,如# data_tables等。。
技术总结:
本篇主要介绍了DataTable的属性和基础使用,选择,排序,左右横滑。此外有粉丝提到如何添加滚动进度条,可以外层包裹Scrollbar,flutter万物皆组件, 如果既要横向滚动,又要纵向滚动,该如何解决呢?这个问题可以自己写代码调试,如有问题可以评论区留言讨论。