Flutter树形视图展示插件flutter_treeview_plus的使用
Flutter树形视图展示插件flutter_treeview_plus的使用
flutter_treeview_plus
是一个用于在 Flutter 应用中展示树形数据的插件。它可以帮助开发者以层级结构的形式展示数据,如组织架构图、文件目录等。

示例代码
以下是 flutter_treeview_plus
插件的一个完整示例代码。
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_treeview_plus/flutter_treeview_plus.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Treeview Plus',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Treeview Plus'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
[@override](/user/override)
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final treeData = <TreeNodeData>[];
final selectedOrganizationChart = <ItemOrganizationChart>{};
[@override](/user/override)
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) async {
final strOrganizationChart =
await rootBundle.loadString('assets/organization_chart.json');
final organizationChartJson = json.decode(strOrganizationChart);
final organizationChart = OrganizationChart(
data: (organizationChartJson['data'] as List<dynamic>?)?.map((e) {
return ItemOrganizationChart.fromJson(e);
}).toList(),
);
final data = organizationChart.data ?? [];
treeData.addAll(
List.generate(
data.length,
(index) => mapOrganizationChartToTreeNodeData(data[index], null),
),
);
setState(() {});
});
super.initState();
}
TreeNodeData mapOrganizationChartToTreeNodeData(
ItemOrganizationChart itemOrganizationChart, TreeNodeData? parent) {
final children = itemOrganizationChart.children ?? [];
final treeNodeData = TreeNodeData(
title: itemOrganizationChart.name ?? '-',
expanded: itemOrganizationChart.isExpanded,
checked: itemOrganizationChart.isChecked,
children: [],
parent: parent,
extra: itemOrganizationChart,
);
final nestedChildren = children.isEmpty
? <TreeNodeData>[]
: children
.map((e) => mapOrganizationChartToTreeNodeData(e, treeNodeData))
.toList();
treeNodeData.children = nestedChildren;
return treeNodeData;
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: treeData.isEmpty
? const Center(
child: CircularProgressIndicator.adaptive(),
)
: FlutterTreeviewPlus(
data: treeData,
showCheckBox: true,
manageParentState: true,
onChange: (List<TreeNodeData> listTreeNode) {
selectedOrganizationChart.clear();
for (final treeNode in listTreeNode) {
handleOnChange(treeNode);
}
/*final listSelectedNames = selectedOrganizationChart.map((e) => e.name ?? '-');
debugPrint('list selected names: $listSelectedNames');*/
},
),
);
}
void handleOnChange(TreeNodeData treeNode) {
final isChecked = treeNode.checked;
final data = treeNode.extra as ItemOrganizationChart;
if (isChecked == null) {
// Check the children
final children = treeNode.children;
if (children.isNotEmpty) {
for (final child in children) {
handleOnChange(child);
}
}
} else if (isChecked) {
// Added to list selected
selectedOrganizationChart.add(data);
}
}
}
class OrganizationChart {
final List<ItemOrganizationChart>? data;
OrganizationChart({required this.data});
[@override](/user/override)
String toString() {
return 'OrganizationChart{data: $data}';
}
}
class ItemOrganizationChart {
final int? id;
final int? pid;
final String? name;
final List<ItemOrganizationChart>? children;
bool isChecked;
bool isExpanded;
ItemOrganizationChart({
required this.id,
required this.pid,
required this.name,
required this.children,
this.isChecked = false,
this.isExpanded = false,
});
factory ItemOrganizationChart.fromJson(Map<String, dynamic> json) {
return ItemOrganizationChart(
id: json['id'],
pid: json['pid'],
name: json['name'],
children: (json['children'] as List<dynamic>?)?
.map(
(e) => ItemOrganizationChart.fromJson(e as Map<String, dynamic>))
.toList(),
);
}
[@override](/user/override)
String toString() {
return 'ItemOrganizationChart{id: $id, pid: $pid, name: $name, children: $children, isChecked: $isChecked, '
'isExpanded: $isExpanded}';
}
}
代码解释
-
导入必要的库
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_treeview_plus/flutter_treeview_plus.dart';
-
定义主应用类
void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); [@override](/user/override) Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Treeview Plus', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(title: 'Flutter Treeview Plus'), ); } }
-
定义主页状态类
class MyHomePage extends StatefulWidget { const MyHomePage({super.key, required this.title}); final String title; [@override](/user/override) State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { final treeData = <TreeNodeData>[]; final selectedOrganizationChart = <ItemOrganizationChart>{}; [@override](/user/override) void initState() { WidgetsBinding.instance.addPostFrameCallback((_) async { final strOrganizationChart = await rootBundle.loadString('assets/organization_chart.json'); final organizationChartJson = json.decode(strOrganizationChart); final organizationChart = OrganizationChart( data: (organizationChartJson['data'] as List<dynamic>?)?.map((e) { return ItemOrganizationChart.fromJson(e); }).toList(), ); final data = organizationChart.data ?? []; treeData.addAll( List.generate( data.length, (index) => mapOrganizationChartToTreeNodeData(data[index], null), ), ); setState(() {}); }); super.initState(); }
-
将数据转换为树节点数据
TreeNodeData mapOrganizationChartToTreeNodeData( ItemOrganizationChart itemOrganizationChart, TreeNodeData? parent) { final children = itemOrganizationChart.children ?? []; final treeNodeData = TreeNodeData( title: itemOrganizationChart.name ?? '-', expanded: itemOrganizationChart.isExpanded, checked: itemOrganizationChart.isChecked, children: [], parent: parent, extra: itemOrganizationChart, ); final nestedChildren = children.isEmpty ? <TreeNodeData>[] : children .map((e) => mapOrganizationChartToTreeNodeData(e, treeNodeData)) .toList(); treeNodeData.children = nestedChildren; return treeNodeData; }
-
构建页面
[@override](/user/override) Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: treeData.isEmpty ? const Center( child: CircularProgressIndicator.adaptive(), ) : FlutterTreeviewPlus( data: treeData, showCheckBox: true, manageParentState: true, onChange: (List<TreeNodeData> listTreeNode) { selectedOrganizationChart.clear(); for (final treeNode in listTreeNode) { handleOnChange(treeNode); } }, ), ); }
-
处理选中状态变化
void handleOnChange(TreeNodeData treeNode) { final isChecked = treeNode.checked; final data = treeNode.extra as ItemOrganizationChart; if (isChecked == null) { // Check the children final children = treeNode.children; if (children.isNotEmpty) { for (final child in children) { handleOnChange(child); } } } else if (isChecked) { // Added to list selected selectedOrganizationChart.add(data); } }
-
定义组织架构数据模型
class OrganizationChart { final List<ItemOrganizationChart>? data; OrganizationChart({required this.data}); [@override](/user/override) String toString() { return 'OrganizationChart{data: $data}'; } } class ItemOrganizationChart { final int? id; final int? pid; final String? name; final List<ItemOrganizationChart>? children; bool isChecked; bool isExpanded; ItemOrganizationChart({ required this.id, required this.pid, required this.name, required this.children, this.isChecked = false, this.isExpanded = false, }); factory ItemOrganizationChart.fromJson(Map<String, dynamic> json) { return ItemOrganizationChart( id: json['id'], pid: json['pid'], name: json['name'], children: (json['children'] as List<dynamic>?)? .map( (e) => ItemOrganizationChart.fromJson(e as Map<String, dynamic>)) .toList(), ); } [@override](/user/override) String toString() { return 'ItemOrganizationChart{id: $id, pid: $pid, name: $name, children: $children, isChecked: $isChecked, ' 'isExpanded: $isExpanded}'; } }
更多关于Flutter树形视图展示插件flutter_treeview_plus的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter树形视图展示插件flutter_treeview_plus的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
flutter_treeview_plus
是一个用于在 Flutter 应用中展示树形结构的插件。它可以帮助你轻松地创建和管理树形视图,支持展开、折叠节点,以及自定义节点的样式和行为。下面是如何使用 flutter_treeview_plus
插件的详细步骤。
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 flutter_treeview_plus
插件的依赖:
dependencies:
flutter:
sdk: flutter
flutter_treeview_plus: ^1.0.0 # 请检查最新版本
然后运行 flutter pub get
来安装依赖。
2. 基本用法
以下是一个简单的例子,展示如何使用 flutter_treeview_plus
来创建一个树形视图。
import 'package:flutter/material.dart';
import 'package:flutter_treeview_plus/flutter_treeview_plus.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('TreeView Example'),
),
body: TreeViewExample(),
),
);
}
}
class TreeViewExample extends StatefulWidget {
@override
_TreeViewExampleState createState() => _TreeViewExampleState();
}
class _TreeViewExampleState extends State<TreeViewExample> {
TreeViewController? _treeViewController;
final List<Node> _nodes = [
Node(
key: '1',
label: 'Node 1',
children: [
Node(
key: '1.1',
label: 'Node 1.1',
),
Node(
key: '1.2',
label: 'Node 1.2',
children: [
Node(
key: '1.2.1',
label: 'Node 1.2.1',
),
Node(
key: '1.2.2',
label: 'Node 1.2.2',
),
],
),
],
),
Node(
key: '2',
label: 'Node 2',
),
];
@override
void initState() {
super.initState();
_treeViewController = TreeViewController(
children: _nodes,
);
}
@override
Widget build(BuildContext context) {
return TreeView(
controller: _treeViewController!,
onExpansionChanged: (key, expanded) {
setState(() {
_treeViewController!.expandNode(key, expanded);
});
},
onNodeTap: (key) {
print('Node $key tapped');
},
);
}
}
3. 主要组件和属性
TreeViewController
: 用于控制树形视图的状态,包括节点的展开和折叠。Node
: 表示树形视图中的一个节点,可以包含子节点。TreeView
: 用于展示树形视图的组件。
4. 自定义节点样式
你可以通过 TreeView
的 nodeBuilder
属性来自定义节点的样式。例如:
TreeView(
controller: _treeViewController!,
onExpansionChanged: (key, expanded) {
setState(() {
_treeViewController!.expandNode(key, expanded);
});
},
onNodeTap: (key) {
print('Node $key tapped');
},
nodeBuilder: (BuildContext context, Node node) {
return Container(
padding: EdgeInsets.all(8.0),
child: Row(
children: [
Icon(Icons.folder),
SizedBox(width: 8.0),
Text(node.label),
],
),
);
},
);
5. 动态更新树形结构
你可以通过 TreeViewController
动态地添加、删除或更新节点。例如:
void _addNode() {
setState(() {
_treeViewController!.addNode(
Node(
key: '3',
label: 'Node 3',
),
parentKey: '1', // Optional: add as a child of Node 1
);
});
}
6. 处理节点事件
你可以通过 onNodeTap
和 onExpansionChanged
来处理节点的点击和展开/折叠事件。
TreeView(
controller: _treeViewController!,
onExpansionChanged: (key, expanded) {
setState(() {
_treeViewController!.expandNode(key, expanded);
});
},
onNodeTap: (key) {
print('Node $key tapped');
},
);