一統天下 flutter - widget 列表類: DataTable - 數據表格
示例如下:
lib\widget\list\data_table.dart
/*
* DataTable - 數據表格
*/
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_demo/helper.dart';
class DataTableDemo extends StatefulWidget {
const DataTableDemo({Key? key}) : super(key: key);
@override
_DataTableDemoState createState() => _DataTableDemoState();
}
class _DataTableDemoState extends State<DataTableDemo> {
var _sortColumnIndex = 0;
var _sortAscending = true;
_getDataTable() {
/// 數據表格
return DataTable(
/// 標題行 DataColumn 集合
columns: _getDataColumnList(),
/// 數據行 DataRow 集合
rows: _getDataRowList(),
/// 標題行的高度
headingRowHeight: 56,
/// 標題行的文本樣式
headingTextStyle: const TextStyle(color: Colors.white),
/// 數據行的高度
dataRowHeight: 40,
/// 數據行的文本樣式
dataTextStyle: const TextStyle(color: Colors.white),
/// 數據行的背景顏色
dataRowColor: MaterialStateProperty.resolveWith((states) {
if (states.contains(MaterialState.selected)) {
return Colors.green; /// 選中狀態的顏色
}
return Colors.red; /// 其他狀態的顏色
}),
/// 列之間的間距
columnSpacing: 56,
/// 左側邊緣與第一列之間的間距,以及右側邊緣與最後一列之間的間距
horizontalMargin: 10,
/// 分隔線的寬度
dividerThickness: 2,
/// 最後一行數據的下面是否要顯示分隔線
showBottomBorder: false,
/// 是否在每行的左側顯示覆選框
showCheckboxColumn: true,
/// 複選框水平方向上的外邊距
checkboxHorizontalMargin: 10,
/// 當前排序的列索引
sortColumnIndex: _sortColumnIndex,
/// 當前排序的方向是否是正向排序
sortAscending: _sortAscending,
/// 點擊標題行中的全選按鈕時的回調
/// 定義這個就要自己寫邏輯,不定義這個則走默認的全選邏輯
/*
onSelectAll: (value) {
},
*/
);
}
_getDataColumnList() {
List<DataColumn> dataColumnList = [];
for (var column in _columnList) {
/// 標題行中的每個列
dataColumnList.add(DataColumn(
/// 需要顯示的內容
label: Text(column.name,),
/// tooltip
tooltip: column.name,
/// 是否右對齊
numeric: false,
/// 點擊標題,觸發排序操作時的回調
onSort: (int columnIndex, bool ascending) {
/// columnIndex - 排序的列的索引
/// ascending - 是否正向排序
log('onSort, columnIndex:$columnIndex, ascending:$ascending');
if (columnIndex != 0 && columnIndex != 2) {
return;
}
setState(() {
_sortColumnIndex = columnIndex;
_sortAscending = ascending;
/// 對數據源排序
_rowList.sort((p1, p2) {
dynamic compareA;
dynamic compareB;
switch (_sortColumnIndex) {
case 0:
compareA = p1.id;
compareB = p2.id;
break;
case 2:
compareA = p1.x1;
compareB = p2.x1;
break;
}
if (_sortAscending) {
return compareA.compareTo(compareB);
}
return compareB.compareTo(compareA);
});
});
},
));
}
return dataColumnList;
}
_getDataRowList() {
List<DataRow> dataRowList = [];
for (var row in _rowList) {
/// 數據行中的每個單元格
dataRowList.add(DataRow(
/// 當前行的單元格集合
cells: [
_getDataCell(row.id.toString()),
_getDataCell(row.name),
_getDataCell(row.x1.toString()),
_getDataCell(row.x2.toString()),
_getDataCell(row.x3.toString()),
_getDataCell(row.x4.toString()),
_getDataCell(row.x5.toString()),
_getDataCell(row.x6.toString()),
_getDataCell(row.x7.toString()),
_getDataCell(row.x8.toString()),
],
/// 當前數據行是否是選中狀態
selected: row.isSelected,
/// 當前數據行的選中狀態發生變化時的回調
onSelectChanged: (isSelected) {
setState(() {
row.isSelected = isSelected!;
});
},
));
}
return dataRowList;
}
_getDataCell(String s) {
/// 單元格
return DataCell(
Text(s),
/// 是否在單元格上顯示編輯按鈕
showEditIcon: false,
/// 單擊事件,類似的有 onTap, onLongPress, onTapDown, onDoubleTap, onTapCancel
onTap: () {
log("onTap");
}
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('title'),),
backgroundColor: Colors.orange,
/// DataTable 不支持滾動,需要藉助 SingleChildScrollView 實現滾動
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
/// 這個主題用於修改排序的提示圖標的顏色,其它的一些無法直接修改的樣式也可以通過這種方式修改,具體用的是什麼主題可以看源代碼
child: Theme(
data: ThemeData(
iconTheme: const IconThemeData(
color: Colors.blue,
),
),
child: _getDataTable(),
),
),
),
);
}
}
class _MyColumn {
const _MyColumn({required this.name});
final String name;
}
class _MyRow {
int id;
String name;
int x1;
int x2;
int x3;
int x4;
int x5;
int x6;
int x7;
int x8;
bool isSelected;
_MyRow(
this.id,
this.name,
this.x1,
this.x2,
this.x3,
this.x4,
this.x5,
this.x6,
this.x7,
this.x8, {
this.isSelected = false,
});
}
var _columnList = const [
_MyColumn(name: '學號'),
_MyColumn(name: '姓名'),
_MyColumn(name: '學科1'),
_MyColumn(name: '學科2'),
_MyColumn(name: '學科3'),
_MyColumn(name: '學科4'),
_MyColumn(name: '學科5'),
_MyColumn(name: '學科6'),
_MyColumn(name: '學科7'),
_MyColumn(name: '學科8'),
];
var _random = Random();
var _rowList = List<_MyRow>.generate(30, (index) =>
_MyRow(index, 'name$index', _random.nextInt(100), _random.nextInt(100), _random.nextInt(100), _random.nextInt(100), _random.nextInt(100), _random.nextInt(100), _random.nextInt(100), _random.nextInt(100)),);