horizontal_data_table
一个 Flutter Widget,用于创建一个在左侧具有固定列的水平表。
用法
此 widget 显示了完整的自定义选项
HorizontalDataTable(
{@required this.leftHandSideColumnWidth,
@required this.rightHandSideColumnWidth,
this.isFixedHeader = false,
this.headerWidgets,
this.leftSideItemBuilder,
this.rightSideItemBuilder,
this.itemCount = 0,
this.leftSideChildren,
this.rightSideChildren,
this.rowSeparatorWidget = const Divider(
color: Colors.transparent,
height: 0.0,
thickness: 0.0,
),
this.elevation = 5.0}
)
- 需要输入左侧列的宽度(leftHandSideColumnWidth)和右侧最大可滚动区域的宽度(rightHandSideColumnWidth)。
- isFixedHeader 用于定义是否使用固定的顶部行标题。如果为 true,则需要 headerWidgets。默认为 false。
- 此 widget 允许通过两种方式设置子项:
a. 直接添加子 widget 列表(leftSideChildren 和 rightSideChildren)
b. (推荐)使用 index builder 为每一行分配 widget。itemCount 是指定行数所必需的。 - rowSeparatorWidget 用于在每一行之间添加分隔线。默认不启用。
- elevation 是滚动开始时标题行和左侧列之间的阴影。默认为 5.0。如果想禁用阴影,请将其设置为 0.0。
示例

import 'package:flutter/material.dart';
import 'package:horizontal_data_table/horizontal_data_table.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: _getBodyWidget(),
);
}
Widget _getBodyWidget() {
return Container(
child: HorizontalDataTable(
leftHandSideColumnWidth: 100,
rightHandSideColumnWidth: 600,
isFixedHeader: true,
headerWidgets: _getTitleWidget(),
leftSideItemBuilder: _generateFirstColumnRow,
rightSideItemBuilder: _generateRightHandSideColumnRow,
itemCount: 100,
rowSeparatorWidget: const Divider(
color: Colors.black54,
height: 1.0,
thickness: 0.0,
),
),
height: MediaQuery.of(context).size.height,
);
}
List<Widget> _getTitleWidget() {
return [
_getTitleItemWidget('Name', 100),
_getTitleItemWidget('Status', 100),
_getTitleItemWidget('Phone', 200),
_getTitleItemWidget('Register', 100),
_getTitleItemWidget('Termination', 200),
];
}
Widget _getTitleItemWidget(String label, double width) {
return Container(
child: Text(label, style: TextStyle(fontWeight: FontWeight.bold)),
width: width,
height: 56,
padding: EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
);
}
Widget _generateFirstColumnRow(BuildContext context, int index) {
return Container(
child: Text('User_$index'),
width: 100,
height: 52,
padding: EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
);
}
Widget _generateRightHandSideColumnRow(BuildContext context, int index) {
return Row(
children: <Widget>[
Container(
child: Row(
children: <Widget>[
Icon(Icons.notifications_active,
color: index % 3 == 0 ? Colors.red : Colors.green),
Text(index % 3 == 0 ? 'Disabled' : 'Active')
],
),
width: 100,
height: 52,
padding: EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
),
Container(
child: Text('+001 9999 9999'),
width: 200,
height: 52,
padding: EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
),
Container(
child: Text('2019-01-01'),
width: 100,
height: 52,
padding: EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
),
Container(
child: Text('N/A'),
width: 200,
height: 52,
padding: EdgeInsets.fromLTRB(5, 0, 0, 0),
alignment: Alignment.centerLeft,
),
],
);
}
}