Flutter组织架构图插件org_chart的使用
Flutter组织架构图插件 org_chart
的使用
org_chart
是一个功能丰富的Flutter插件,用于创建可拖拽、缩放和平移的组织架构图。它支持多种自定义选项,如节点形状、箭头样式等,并且适用于所有Flutter支持的平台。
重要提示
这是我的第一个包,如果你有任何想法或建议,请不要犹豫联系我。欢迎提交问题或拉取请求。
待办事项
- [✅] 实现相对稳定且易于定制的API
- [✅] 添加方向支持
- [✅] 添加箭头绘制自定义
- ❌ 添加箭头样式
- ❌ 添加箭头动画
- ❌ 编写详细文档
如果你有更多需要添加的内容,请提交问题或拉取请求!
组织架构图功能
- 拖拽和放置
- 缩放和平移
- 搜索
- 折叠/展开节点
- 极易定制的节点形状
警告
如果在 onDrop
函数中 isTargetSubnode
为 true
,则将目标设置为拖动节点的父节点会导致应用崩溃!现在这个检查会在后台自动完成。
使用方法
要使用此包,请在 pubspec.yaml
文件中添加 org_chart
作为依赖项。
dependencies:
org_chart: ^latest_version
别忘了导入包:
import 'package:org_chart/org_chart.dart';
控制器实现
final OrgChartController<Map> orgChartController = OrgChartController<Map>(
boxSize: const Size(200, 100),
items: [
{"title": 'CEO', "id": '1', "to": null},
{"title": 'HR Manager: John', "id": '2', "to": '1'},
{"title": 'HR Officer: Jane', "id": '3', "to": '2'},
{"title": 'Project Manager: Zuher', "id": '4', "to": '1'},
],
idProvider: (data) => data["id"],
toProvider: (data) => data["to"],
toSetter: (data, newID) => data["to"] = newID,
);
小部件实现
OrgChart(
controller: orgChartController,
curve: Curves.elasticOut, // 自定义动画曲线
duration: 500, // 自定义动画持续时间
isDraggable: true, // 启用或禁用拖拽
builder: (details) {
return Card(
color: details.beingDragged
? Colors.blue
: details.isOverlapped
? Colors.green
: null,
elevation: 10,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(details.item["title"]),
ElevatedButton(
onPressed: () {
details.hideNodes(!details.nodesHidden);
},
child: Text(details.nodesHidden ? 'Press to Unhide' : 'Press to Hide'),
),
],
),
),
);
},
optionsBuilder: (item) {
return [
const PopupMenuItem(value: 'Remove', child: Text('Remove')),
];
},
onOptionSelect: (item, value) {
if (value == 'Remove') {
orgChartController.removeItem(item["id"], ActionOnNodeRemoval.unlink);
}
},
onDrop: (dragged, target, isTargetSubnode) {
if (isTargetSubnode) {
showDialog(
context: context,
builder: (_) {
return AlertDialog(
title: const Text('Error'),
content: const Text('You cannot drop a node on a subnode'),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('OK'),
),
],
);
},
);
orgChartController.calculatePosition();
return;
}
dragged["to"] = target["id"];
orgChartController.calculatePosition();
},
)
示例代码
以下是一个完整的示例代码,展示了如何使用 org_chart
插件来创建一个简单的组织架构图:
import 'package:flutter/material.dart';
import 'package:org_chart/org_chart.dart';
void main() {
runApp(const MainApp());
}
class MainApp extends StatefulWidget {
const MainApp({super.key});
[@override](/user/override)
State<MainApp> createState() => _MainAppState();
}
class _MainAppState extends State<MainApp> {
[@override](/user/override)
Widget build(BuildContext context) {
return const MaterialApp(home: Example2());
}
}
class Example2 extends StatefulWidget {
const Example2({super.key});
[@override](/user/override)
State<Example2> createState() => _Example2State();
}
class _Example2State extends State<Example2> {
final OrgChartController<Map> orgChartController = OrgChartController<Map>(
boxSize: const Size(150, 80),
items: [
{"id": '0', "text": 'Main Block'},
{"id": '1', "text": 'Block 2', "to": '0'},
{"id": '2', "text": 'Block 3', "to": '0'},
{"id": '3', "text": 'Block 4', "to": '1'},
],
idProvider: (data) => data["id"],
toProvider: (data) => data["to"],
toSetter: (data, newID) => data["to"] = newID,
);
[@override](/user/override)
Widget build(BuildContext context) {
return Stack(
children: [
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.blue.shade100, Colors.blue.shade200],
begin: Alignment.bottomLeft,
end: Alignment.topRight,
),
),
child: Scaffold(
backgroundColor: Colors.transparent,
body: Stack(
children: [
Center(
child: OrgChart<Map>(
cornerRadius: 10,
controller: orgChartController,
isDraggable: true,
linePaint: Paint()
..color = Colors.black
..strokeWidth = 5
..style = PaintingStyle.stroke,
onTap: (item) {
orgChartController.addItem({
"id": orgChartController.uniqueNodeId,
"text": 'New Block',
"to": item["id"],
});
setState(() {});
},
onDoubleTap: (item) async {
String? text = await getBlockText(context, item);
if (text != null) setState(() => item["text"] = text);
},
builder: (details) {
return GestureDetector(
child: Card(
elevation: 5,
color: details.isBeingDragged
? Colors.green.shade100
: details.isOverlapped
? Colors.red.shade200
: Colors.teal.shade50,
child: Center(
child: Text(
details.item["text"],
style: TextStyle(color: Colors.purple.shade900, fontSize: 20),
),
),
),
);
},
optionsBuilder: (item) {
return [
const PopupMenuItem(value: 'Remove', child: Text('Remove')),
];
},
onOptionSelect: (item, value) {
if (value == 'Remove') {
orgChartController.removeItem(item["id"], ActionOnNodeRemoval.unlink);
}
},
onDrop: (dragged, target, isTargetSubnode) {
if (isTargetSubnode) {
showDialog(
context: context,
builder: (_) {
return AlertDialog(
title: const Text('Error'),
content: const Text('You cannot drop a node on a subnode'),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('OK'),
),
],
);
},
);
orgChartController.calculatePosition();
return;
}
dragged["to"] = target["id"];
orgChartController.calculatePosition();
},
),
),
const Positioned(
bottom: 20,
left: 20,
child: Text(
'Tap to add a node, double tap to change text\n'
'drag and drop to change hierarchy\n'
'right click / tap and hold to remove \n'
'Drag in the empty space to pan the chart, zoom in and out.\n',
),
)
],
),
floatingActionButton: FloatingActionButton.extended(
label: const Text('Reset & Change Orientation'),
onPressed: () {
orgChartController.switchOrientation();
},
),
),
),
],
);
}
Future<String?> getBlockText(BuildContext context, Map<dynamic, dynamic> item) async {
final String? text = await showDialog(
context: context,
builder: (context) {
String text = item["text"];
return AlertDialog(
title: const Text('Enter Text'),
content: TextFormField(
initialValue: item["text"],
onChanged: (value) {
text = value;
},
),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('Cancel'),
),
TextButton(
onPressed: () {
Navigator.of(context).pop(text);
},
child: const Text('OK'),
),
],
);
},
);
return text;
}
}
更多关于Flutter组织架构图插件org_chart的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter组织架构图插件org_chart的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter中使用org_chart
插件来创建组织架构图的示例代码。假设你已经安装了org_chart
插件,可以通过以下步骤来实现。
1. 添加依赖
首先,确保在pubspec.yaml
文件中添加了org_chart
的依赖:
dependencies:
flutter:
sdk: flutter
org_chart: ^最新版本号 # 请替换为最新版本号
然后运行flutter pub get
来安装依赖。
2. 导入插件
在你的Flutter项目的Dart文件中导入org_chart
插件:
import 'package:org_chart/org_chart.dart';
3. 创建数据模型
为了创建组织架构图,你需要一个数据模型来表示每个节点(员工)。这里是一个简单的示例:
class OrgNode {
String name;
List<OrgNode> children;
OrgNode({required this.name, this.children = const []});
}
4. 构建组织架构图
在你的Flutter Widget中,使用OrgChart
组件来构建组织架构图。以下是一个完整的示例:
import 'package:flutter/material.dart';
import 'package:org_chart/org_chart.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Org Chart Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: OrgChartScreen(),
);
}
}
class OrgChartScreen extends StatefulWidget {
@override
_OrgChartScreenState createState() => _OrgChartScreenState();
}
class _OrgChartScreenState extends State<OrgChartScreen> {
// 创建组织架构数据
final OrgNode rootNode = OrgNode(
name: 'CEO',
children: [
OrgNode(
name: 'CTO',
children: [
OrgNode(name: 'Developer 1'),
OrgNode(name: 'Developer 2'),
],
),
OrgNode(
name: 'CFO',
children: [
OrgNode(name: 'Accountant 1'),
OrgNode(name: 'Accountant 2'),
],
),
OrgNode(
name: 'CHO',
children: [
OrgNode(name: 'HR 1'),
OrgNode(name: 'HR 2'),
],
),
],
);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Org Chart Example'),
),
body: OrgChart(
data: rootNode,
nodeBuilder: (context, node) {
return OrgChartNode(
title: Text(node.name),
subTitle: node.children.isEmpty
? null
: Text('${node.children.length} Direct Reports'),
);
},
),
);
}
}
5. 运行应用
确保你的开发环境已经配置好,然后运行应用:
flutter run
这个示例展示了如何使用org_chart
插件来创建一个简单的组织架构图。你可以根据需要自定义节点样式、布局和其他功能。请查阅org_chart
插件的官方文档以获取更多详细信息和高级用法。