Flutter可扩展表格插件flutter_expandable_table的使用
Flutter可扩展表格插件flutter_expandable_table的使用
Expandable Table
ExpandableTable
是一个Flutter小部件,用于创建具有固定表头和第一列的表格。您可以创建嵌套的行/列,并将它们分组为可扩展的行/列。
ExpandableTable |
---|
Features
- 表头和第一列固定
- 支持垂直和水平滚动
- 可定制动画时长和曲线
- 为每一行定义特定高度
- 为每一列定义特定宽度
- 构建单元格内容时访问单元格地址
- 构建单元格内容时访问父行和列
Usage
Installation
在 pubspec.yaml
文件中添加以下依赖:
dependencies:
flutter_expandable_table: <last-release>
Basic Setup
完整的示例代码可以在 GitHub 上找到。
return ExpandableTable(
firstHeaderCell: ExpandableTableCell(
child: Text('Simple\nTable'),
),
headers: headers,
rows: rows,
);
Use with the Controller
您可以创建一个外部控制器来动态管理表格,例如在其中添加或删除行。
//... Inside Widget State
late ExpandableTableController controller;
@override
void initState() {
controller = ExpandableTableController(
firstHeaderCell: ExpandableTableCell(child: Container()),
headers: [],
rows: [],
headerHeight: 263,
defaultsColumnWidth: 200,
firstColumnWidth: 300,
scrollShadowColor: AppColors.black,
);
super.initState();
}
void _onEvent(){
controller.rows.add(...your code...);
}
@Override
Widget build(BuildContext context) {
return ExpandableTable(
controller: controller,
);
}
ExpandableTable Properties
firstHeaderCell
: 左上角单元格,即第一个表头单元格。headers
: 包含所有列标题的列表,每个标题可以包含进一步的标题列表,允许创建嵌套和可扩展的列。rows
: 包含表格所有行的列表,每行可以包含进一步的行列表,允许创建嵌套和可扩展的行。headerHeight
: 每个列标题的高度,即第一行的高度。firstColumnWidth
: 第一列的宽度。defaultsColumnWidth
: 所有列的默认宽度,可以为每个单独的列重新定义。defaultsRowHeight
: 所有行的默认高度,可以为每个单独的行重新定义。duration
: 行/列扩展渲染动画的持续时间。curve
: 行/列扩展渲染动画的曲线。scrollShadowDuration
: 阴影动画的持续时间。scrollShadowFadeInCurve
: 阴影出现动画的曲线。scrollShadowFadeOutCurve
: 阴影消失动画的曲线。scrollShadowColor
: 阴影的颜色。scrollShadowSize
: 阴影的大小。visibleScrollbar
: 水平和垂直滚动条的可见性。trackVisibilityScrollbar
: 滚动条轨道是否可见。thumbVisibilityScrollbar
: 滚动条拇指是否可见,即使没有进行滚动操作。expanded
: 表格是否扩展,以填充水平和垂直轴上的可用空间。
示例代码
以下是使用 flutter_expandable_table
的完整示例代码:
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
// ignore: depend_on_referenced_packages
import 'package:flutter_expandable_table/flutter_expandable_table.dart';
const Color _primaryColor = Color(0xFF1e2f36); //corner
const Color _accentColor = Color(0xFF0d2026); //background
const TextStyle _textStyle = TextStyle(color: Colors.white);
void main() => runApp(const _MyApp());
class _MyApp extends StatelessWidget {
const _MyApp();
@override
Widget build(BuildContext context) => MaterialApp(
title: 'ExpandableTable Example',
theme: ThemeData(primarySwatch: Colors.grey),
home: const _MyHomePage(),
scrollBehavior: _AppCustomScrollBehavior(),
);
}
class _DefaultCellCard extends StatelessWidget {
final Widget child;
const _DefaultCellCard({
required this.child,
});
@override
Widget build(BuildContext context) => Container(
color: _primaryColor,
margin: const EdgeInsets.all(1),
child: child,
);
}
class _MyHomePage extends StatefulWidget {
const _MyHomePage();
@override
State<_MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<_MyHomePage> {
ExpandableTableCell _buildCell(String content, {CellBuilder? builder}) =>
ExpandableTableCell(
child: builder != null
? null
: _DefaultCellCard(
child: Center(
child: Text(
content,
style: _textStyle,
),
),
),
builder: builder,
);
ExpandableTableCell _buildFirstRowCell() => ExpandableTableCell(
builder: (context, details) => _DefaultCellCard(
child: Padding(
padding: const EdgeInsets.only(left: 16.0),
child: Row(
children: [
SizedBox(
width: 24 * details.row!.address.length.toDouble(),
child: details.row?.children != null
? Align(
alignment: Alignment.centerRight,
child: AnimatedRotation(
duration: const Duration(milliseconds: 500),
turns: details.row?.childrenExpanded == true
? 0.25
: 0,
child: const Icon(
Icons.keyboard_arrow_right,
color: Colors.white,
),
),
)
: null,
),
Text(
'${details.row!.address.length > 1 ? details.row!.address.skip(1).map((e) => 'Sub ').join() : ''}Row ${details.row!.address.last}',
style: _textStyle,
),
],
),
),
),
);
ExpandableTable _buildSimpleTable() {
const int columnsCount = 20;
const int rowsCount = 20;
// 创建表头
final List<ExpandableTableHeader> headers = List.generate(
columnsCount - 1,
(index) => ExpandableTableHeader(
width: index % 2 == 0 ? 200 : 150,
cell: _buildCell('Column $index'),
),
);
// 创建行
final List<ExpandableTableRow> rows = List.generate(
rowsCount,
(rowIndex) => ExpandableTableRow(
height: rowIndex % 2 == 0 ? 50 : 70,
firstCell: _buildCell('Row $rowIndex'),
cells: List<ExpandableTableCell>.generate(
columnsCount - 1,
(columnIndex) => _buildCell('Cell $rowIndex:$columnIndex'),
),
),
);
return ExpandableTable(
firstHeaderCell: _buildCell('Simple\nTable'),
headers: headers,
scrollShadowColor: _accentColor,
rows: rows,
visibleScrollbar: true,
trackVisibilityScrollbar: true,
thumbVisibilityScrollbar: true,
);
}
static const int columnsCount = 20;
static const int subColumnsCount = 2;
static const int rowsCount = 6;
static const int subRowsCount = 3;
static const int totalColumns = columnsCount + subColumnsCount;
List<ExpandableTableRow> _generateRows(int quantity, {int depth = 0}) {
final bool generateLegendRow = (depth == 0 || depth == 2);
return List.generate(
quantity,
(rowIndex) => ExpandableTableRow(
firstCell: _buildFirstRowCell(),
children: ((rowIndex == 3 || rowIndex == 2) && depth < 3)
? _generateRows(subRowsCount, depth: depth + 1)
: null,
cells: !(generateLegendRow && (rowIndex == 3 || rowIndex == 2))
? List<ExpandableTableCell>.generate(
totalColumns,
(columnIndex) => _buildCell('Cell $rowIndex:$columnIndex'),
)
: null,
legend: generateLegendRow && (rowIndex == 3 || rowIndex == 2)
? const _DefaultCellCard(
child: Align(
alignment: FractionalOffset.centerLeft,
child: Padding(
padding: EdgeInsets.only(left: 24.0),
child: Text(
'This is row legend',
style: _textStyle,
),
),
),
)
: null,
),
);
}
ExpandableTable _buildExpandableTable() {
// 创建子表头
final List<ExpandableTableHeader> subHeader = List.generate(
subColumnsCount,
(index) => ExpandableTableHeader(
cell: _buildCell('Sub Column $index'),
),
);
// 创建表头
final List<ExpandableTableHeader> headers = List.generate(
columnsCount,
(index) => ExpandableTableHeader(
cell: _buildCell(
'${index == 1 ? 'Expandable\nColumn' : 'Column'} $index'),
children: index == 1 ? subHeader : null),
);
return ExpandableTable(
firstHeaderCell: _buildCell('Expandable\nTable'),
rows: _generateRows(rowsCount),
headers: headers,
defaultsRowHeight: 60,
defaultsColumnWidth: 150,
firstColumnWidth: 250,
scrollShadowColor: _accentColor,
visibleScrollbar: true,
expanded: false,
);
}
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text(
' Simple Table | Expandable Table'),
centerTitle: true,
),
body: Container(
color: _accentColor,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: _buildSimpleTable(),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: _buildExpandableTable(),
),
),
],
),
),
);
}
class _AppCustomScrollBehavior extends MaterialScrollBehavior {
@override
Set<PointerDeviceKind> get dragDevices => {
PointerDeviceKind.touch,
PointerDeviceKind.mouse,
PointerDeviceKind.trackpad,
};
}
通过以上代码,您可以创建一个简单的可扩展表格,并根据需要自定义其外观和行为。希望这些信息对您有所帮助!
更多关于Flutter可扩展表格插件flutter_expandable_table的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter可扩展表格插件flutter_expandable_table的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter中使用flutter_expandable_table
插件来实现可扩展表格的示例代码。
首先,你需要在你的pubspec.yaml
文件中添加flutter_expandable_table
依赖:
dependencies:
flutter:
sdk: flutter
flutter_expandable_table: ^latest_version # 请替换为实际的最新版本号
然后运行flutter pub get
来安装依赖。
接下来是一个完整的示例代码,展示如何使用flutter_expandable_table
来创建一个可扩展的表格:
import 'package:flutter/material.dart';
import 'package:flutter_expandable_table/flutter_expandable_table.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Expandable Table Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: ExpandableTableScreen(),
);
}
}
class ExpandableTableScreen extends StatefulWidget {
@override
_ExpandableTableScreenState createState() => _ExpandableTableScreenState();
}
class _ExpandableTableScreenState extends State<ExpandableTableScreen> {
final List<Map<String, dynamic>> tableData = [
{
'header': 'Header 1',
'rows': [
{'cell1': 'Row 1, Cell 1', 'cell2': 'Row 1, Cell 2'},
{'cell1': 'Row 2, Cell 1', 'cell2': 'Row 2, Cell 2'},
],
},
{
'header': 'Header 2',
'rows': [
{'cell1': 'Row 1, Cell 1', 'cell2': 'Row 1, Cell 2'},
{'cell1': 'Row 2, Cell 1', 'cell2': 'Row 2, Cell 2'},
{'cell1': 'Row 3, Cell 1', 'cell2': 'Row 3, Cell 2'},
],
},
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Expandable Table Example'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: ExpandableTable(
tableData: tableData,
headerStyle: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
cellStyle: TextStyle(
fontSize: 16,
),
onRowTap: (index, rowIndex) {
print("Header index: $index, Row index: $rowIndex");
},
),
),
);
}
}
在这个示例中:
- 依赖安装:我们在
pubspec.yaml
文件中添加了flutter_expandable_table
依赖。 - 数据结构:
tableData
是一个包含表头和对应行的列表。每个表头映射到一个包含多个行的列表,每个行又是一个包含单元格数据的映射。 - UI构建:
- 使用
Scaffold
构建应用的主界面。 - 使用
AppBar
添加一个应用栏。 - 使用
Padding
为内容添加一些内边距。 - 使用
ExpandableTable
构建可扩展表格,并传入tableData
作为数据源。 headerStyle
和cellStyle
用于定义表头和单元格的文本样式。onRowTap
是一个回调函数,当用户点击某一行时会触发,这里简单地打印了表头和行的索引。
- 使用
这个示例展示了如何使用flutter_expandable_table
插件来创建一个简单的可扩展表格,并处理行的点击事件。你可以根据需要进一步自定义和扩展这个示例。