Flutter甘特图展示插件gantt_view的使用
Flutter甘特图展示插件gantt_view的使用
特性
- 固定的任务名称列
- 固定的日期图例行
- 可自定义的任务栏颜色
- 可自定义的任务栏高度
- 可自定义的任务栏间距
- 可自定义的任务栏圆角半径
- 能够在日视图和周视图之间切换
- 显示周末的不同颜色
- 可自定义周末颜色
- 自定义高亮日期
- 可自定义高亮日期颜色
- 任务栏悬停或点击时显示提示信息
- 可自定义提示样式
使用
所有需要做的就是传入一个带有List<GridRow>
的GanttChart<T>
小部件。List<GridRow>
是一个包含<ActivityGridRow>
和TaskGridRow
的对象列表,构造方法的例子可以在example\lib\main.dart
文件中找到。
该插件还提供了基本的主题选项,用于自定义GanttChart
的外观,例如改变行的外观以及是否显示头部。
ActivityGridRow
和TaskGridRow
是GanttChart
中可以显示的两种类型的行。ActivityGridRow
是一种显示任务组标题的行,而TaskGridRow
是一种显示任务的行。要自定义行的外观,可以向GanttChart
小部件提供一个GanttRowStyle
。GanttRowStyle
有两个字段,activityLabelBuilder
和taskLabelBuilder
,分别用于自定义ActivityGridRow
和TaskGridRow
的外观。
其他自定义选项包括更改网格线的颜色、周末列的颜色以及高亮日期的颜色。GanttChart
还可以在悬停或点击任务时显示提示信息。
GanttChart<ExampleEventItem>(
rows: _items.toRows(),
style: GanttStyle(
columnWidth: 100,
barHeight: 16,
timelineAxisType: TimelineAxisType.daily,
tooltipType: TooltipType.hover,
taskBarColor: Colors.blue.shade400,
activityLabelColor: Colors.blue.shade500,
taskLabelColor: Colors.blue.shade900,
taskLabelBuilder: (task) => TaskLabel(task),
gridColor: Colors.grey.shade300,
taskBarRadius: 8,
activityLabelBuilder: (activity) => ActivityLabel(activity),
axisDividerColor: Colors.grey.shade500,
tooltipColor: Colors.redAccent,
tooltipPadding:
const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
weekendColor: Colors.grey.shade200,
snapToDay: false,
),
dateLines: [
GanttDateLine(
date: DateTime.timestamp(), width: 2, color: Colors.orangeAccent),
GanttDateLine(
date: DateTime.timestamp().add(const Duration(days: 2)),
),
],
)
样式
属性 | 类型 |
---|---|
taskBarColor | Color |
taskBarRadius | double |
taskLabelColor | Color |
activityLabelColor | Color |
chartTitleBuilder | Widget Function()? |
taskLabelBuilder | Widget Function(TaskGridRow) |
activityLabelBuilder | Widget Function(ActivityGridRow activity)? |
yearLabelBuilder | Widget Function(int year) |
monthLabelBuilder | Widget Function(Month month) |
dayLabelBuilder | Widget Function(int day) |
gridColor | Color? |
weekendColor | Color? |
holidayColor | Color |
axisDividerColor | Color? |
tooltipColor | Color |
tooltipStyle | TextStyle |
tooltipPadding | EdgeInsets |
tooltipRadius | double |
barHeight | double |
columnWidth | double |
tooltipWidth | double |
labelColumnWidth | double |
snapToDay | bool |
showYear | bool |
showMonth | bool |
showDay | bool |
timelineAxisType | TimelineAxisType |
tooltipType | TooltipType |
其他信息
这是一个正在进行中的项目,尚未准备好用于生产环境。API可能会发生变化。欢迎提供反馈,也欢迎提交拉取请求。
待办事项
- ❌ 添加缩放功能
- ✅ 添加自定义单个任务栏颜色的功能
- ❌ 添加为整个图表定义自定义开始和结束时间的功能
- ❌ 测试
- ❌ 添加定义图例高度、标签列宽度的功能,覆盖自动计算的值
- ❌ 添加隐藏图例的功能
- ❌ 添加隐藏标题/标签的功能
- ❌ 添加设置一周第一天的功能
- ❌ 添加将高亮日和周末日设置为纯色的功能,以便任务栏不可见
- ❌ 添加滚动条
- ✅ 添加日期线以允许用户显示重要日期
当前已知问题
- ❌ 有时在实例化时,图表的平移偏移没有正确更新,导致平移速度比预期慢。
- ❌ 大量数据项列表可能导致图表渲染缓慢,原因如下:
- 将大量数据排序为活动和任务;
- 基于最长标签计算标签列的宽度;
- 目前通过为每个标签运行一个实用函数来获取宽度,然后取所有标签的最大宽度,这效率不高。
- ✅ 当调整大小时,图表可能会尝试渲染超出其边界的区域,而不是更新平移偏移到新边界。
- ❌ 非UTC时间的日期在跨越夏令时时区变更时可能会出现问题,因为图表不考虑夏令时。
- ❌ 在网页端,有时使用水平鼠标滚轮无法进行水平滚动。
示例代码
import 'package:example/data.dart';
import 'package:flutter/material.dart';
import 'package:gantt_view/gantt_view.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
useMaterial3: true,
),
home: const MyHomePage(),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
[@override](/user/override)
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final List<ExampleEventItem> _items = Data.dummyData;
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
body: GanttChart<ExampleEventItem>(
rows: _items.toRows(),
showCurrentDate: true,
style: GanttStyle(
columnWidth: 50,
barHeight: 16,
timelineAxisType: TimelineAxisType.daily,
tooltipType: TooltipType.hover,
taskBarColor: Colors.blue.shade400,
activityLabelColor: Colors.blue.shade500,
taskLabelColor: Colors.blue.shade900,
taskLabelBuilder: (task) => Container(
padding: const EdgeInsets.all(4),
child: Text(
task.data.title,
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
gridColor: Colors.grey.shade300,
taskBarRadius: 8,
activityLabelBuilder: (activity) => Container(
padding: const EdgeInsets.all(4),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
activity.label!,
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
const Text(
'A subtitle',
style: TextStyle(
fontStyle: FontStyle.italic,
color: Colors.white,
),
),
],
),
),
axisDividerColor: Colors.grey.shade500,
tooltipColor: Colors.redAccent,
tooltipPadding:
const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
weekendColor: Colors.grey.shade200,
dateLineColor: Colors.red,
snapToDay: false,
),
dateLines: [
GanttDateLine(
date: DateTime.timestamp(), width: 2, color: Colors.orangeAccent),
GanttDateLine(
date: DateTime.timestamp().add(const Duration(days: 2)),
),
],
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.redAccent,
onPressed: () => setState(() => _items.addAll(Data.dummyData)),
child: const Icon(Icons.restore, color: Colors.white),
),
);
}
}
extension on DateTime {
String get formattedDate => '$day/$month/$year';
}
extension on List<ExampleEventItem> {
List<GridRow> toRows() {
List<GridRow> rows = [];
Map<String, List<TaskGridRow<ExampleEventItem>>> labelTasks = {};
sort((a, b) => a.start.compareTo(b.start));
for (var item in this) {
final label = item.group;
(labelTasks[label] ??= []).add(TaskGridRow<ExampleEventItem>(
data: item,
startDate: item.start,
endDate: item.end,
tooltip: '${item.title}\n${item.start.formattedDate} - ${item.end.formattedDate}',
));
}
for (var label in labelTasks.keys) {
rows.add(ActivityGridRow(label));
rows.addAll(labelTasks[label]!);
}
return rows;
}
}
更多关于Flutter甘特图展示插件gantt_view的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复