Flutter递归树结构展示插件recursive_tree_flutter的使用
Flutter递归树结构展示插件recursive_tree_flutter的使用
Table of Contents
简介
recursive_tree_flutter
是一个用于构建和可视化树数据结构的Flutter库。它不仅关注UI界面,更注重树数据结构本身,支持多种特殊的UI样式。例如,它可以更新树节点、返回选中的节点列表或叶子节点列表等。
代码示例
下面是一个简单的例子,展示了如何使用 recursive_tree_flutter
构建一个单选可扩展树:
import 'package:flutter/material.dart';
import 'package:recursive_tree_flutter/recursive_tree_flutter.dart';
class ExTreeSingleChoice extends StatefulWidget {
const ExTreeSingleChoice({super.key});
@override
State<ExTreeSingleChoice> createState() => _ExTreeSingleChoiceState();
}
class _ExTreeSingleChoiceState extends State<ExTreeSingleChoice> {
late TreeType<CustomNodeType> _tree;
final TextEditingController _textController = TextEditingController();
@override
void initState() {
_tree = sampleTree();
super.initState();
}
@override
void dispose() {
_textController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
child: Scaffold(
appBar: AppBar(
title: const Text("Example Single Choice Expandable Tree"),
),
body: Column(
children: [
Expanded(
flex: 4,
child: SingleChildScrollView(
child: _VTSNodeWidget(
_tree,
onNodeDataChanged: () => setState(() {}),
),
),
),
Expanded(
flex: 1,
child: TextFormField(
controller: _textController,
decoration: const InputDecoration(
hintText: "PRESS ENTER TO UPDATE",
),
onFieldSubmitted: (value) {
updateTreeWithSearchingTitle(_tree, value);
setState(() {});
},
),
),
],
),
),
);
}
}
class _VTSNodeWidget extends StatefulWidget {
const _VTSNodeWidget(
this.tree, {
required this.onNodeDataChanged,
});
final TreeType<CustomNodeType> tree;
final VoidCallback onNodeDataChanged;
@override
State<_VTSNodeWidget> createState() => _VTSNodeWidgetState();
}
class _VTSNodeWidgetState<T extends AbsNodeType> extends State<_VTSNodeWidget>
with SingleTickerProviderStateMixin, ExpandableTreeMixin<CustomNodeType> {
final Tween<double> _turnsTween = Tween<double>(begin: -0.25, end: 0.0);
@override
initState() {
super.initState();
initTree();
initRotationController();
if (tree.data.isExpanded) {
rotationController.forward();
}
}
@override
void initTree() {
tree = widget.tree;
}
@override
void initRotationController() {
rotationController = AnimationController(
duration: const Duration(milliseconds: 300),
vsync: this,
);
}
@override
void dispose() {
disposeRotationController();
super.dispose();
}
@override
Widget build(BuildContext context) => buildView();
@override
Widget buildNode() {
if (!widget.tree.data.isShowedInSearching) return const SizedBox.shrink();
return InkWell(
onTap: updateStateToggleExpansion,
child: Row(
children: [
buildRotationIcon(),
Expanded(child: buildTitle()),
buildTrailing(),
],
),
);
}
Widget buildRotationIcon() {
return RotationTransition(
turns: _turnsTween.animate(rotationController),
child: tree.isLeaf
? Container()
: IconButton(
iconSize: 16,
icon: const Icon(Icons.expand_more, size: 16.0),
onPressed: updateStateToggleExpansion,
),
);
}
Widget buildTitle() {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 6.0),
child: Text(
tree.data.title + (tree.isLeaf ? "" : " (${tree.children.length})"),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
);
}
Widget buildTrailing() {
if (tree.data.isUnavailable) {
return const Icon(Icons.close_rounded, color: Colors.red);
}
if (tree.isLeaf) {
return Checkbox(
value: tree.data.isChosen!,
onChanged: (value) {
updateTreeSingleChoice(tree, !tree.data.isChosen!);
widget.onNodeDataChanged();
},
);
}
return const SizedBox.shrink();
}
@override
List<Widget> generateChildrenNodesWidget(List<TreeType<CustomNodeType>> list) =>
List.generate(
list.length,
(int index) => _VTSNodeWidget(
list[index],
onNodeDataChanged: widget.onNodeDataChanged,
),
);
@override
void updateStateToggleExpansion() => setState(() => toggleExpansion());
}
特性
- 构建树数据结构(Dart代码)。
- 提供多种树操作函数,如查找节点、文本搜索、更新多选/单选树等。
- 支持懒加载以在运行时展开树。
- 树数据结构可以独立于Flutter UI使用。
- 使用Flutter可视化树结构。
- 允许自定义Flutter UI以满足特定需求。
内容
树数据结构 (Dart代码)
树数据结构包括内节点和叶节点,类似于计算机上的目录树结构。主要类如下:
- AbsNodeType:抽象类,表示节点的数据类型。
- TreeType:树数据结构,包含节点数据和子节点列表。
辅助函数 (Dart代码)
提供了多个与树遍历和更新相关的函数,如:
isChosenAll(tree)
:检查当前树的所有子节点是否被选中。findRoot(tree)
:查找根节点。searchAllTreesWithTitleDFS(tree, text, result)
:使用DFS算法搜索包含特定文本的节点。
Flutter UI 树
提供了多种UI树组件,如:
- StackWidget:使用堆栈方法构建的UI树。
- ExpandableTreeWidget:使用可扩展方法构建的UI树。
- VTSDepartmentTreeWidget:另一个使用可扩展方法构建的UI树。
基于 ExpandableTreeMixin 的可扩展树的工作原理
可扩展UI树的结构如下:
SingleChildScrollView( // 树是可滚动的
- NodeWidget (root)
-- NodeWidget
+++ NodeWidget
+++ NodeWidget
+++ NodeWidget
-- NodeWidget
+++ NodeWidget
...
)
NodeWidget
是一个递归构建的 StatefulWidget
,包裹在 SingleChildScrollView
中以提供滚动功能。更新树(数据)将改变 NodeWidget
的状态/UI。NodeWidget
继承了 ExpandableTreeMixin
,提供了初始化树、旋转控制器、构建节点等功能。
BSD-3-Clause License
该库遵循 BSD-3-Clause 许可证,允许自由分发和使用源代码和二进制形式,但需保留版权声明和免责声明。
通过以上内容,您可以更好地理解和使用 recursive_tree_flutter
插件来构建和展示递归树结构。希望这些信息对您有所帮助!
更多关于Flutter递归树结构展示插件recursive_tree_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter递归树结构展示插件recursive_tree_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用recursive_tree_flutter
插件来展示递归树结构的代码示例。
首先,确保你已经在pubspec.yaml
文件中添加了recursive_tree_flutter
插件的依赖:
dependencies:
flutter:
sdk: flutter
recursive_tree_flutter: ^最新版本号 # 替换为实际最新版本号
然后,运行flutter pub get
来安装依赖。
接下来是一个完整的示例,展示如何使用recursive_tree_flutter
插件来展示递归树结构。
main.dart
import 'package:flutter/material.dart';
import 'package:recursive_tree_flutter/recursive_tree_flutter.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Recursive Tree Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// 示例树数据
final List<TreeNode> treeData = [
TreeNode(
title: 'Root',
children: [
TreeNode(
title: 'Child 1',
children: [
TreeNode(title: 'Grandchild 1'),
TreeNode(title: 'Grandchild 2'),
],
),
TreeNode(
title: 'Child 2',
children: [
TreeNode(title: 'Grandchild 3'),
],
),
],
),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Recursive Tree Demo'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: RecursiveTreeView(
nodes: treeData,
nodeBuilder: (context, nodeData) {
return ListTile(
title: Text(nodeData.title),
trailing: Icon(Icons.arrow_drop_down),
onTap: () {
// Handle node tap if needed
},
);
},
),
),
);
}
}
// TreeNode 数据模型
class TreeNode {
String title;
List<TreeNode> children;
TreeNode({required this.title, this.children = const []});
}
解释
- 依赖添加:在
pubspec.yaml
中添加recursive_tree_flutter
依赖。 - 数据模型:定义一个
TreeNode
类来表示树的节点,每个节点有一个标题和可选的子节点列表。 - UI 组件:
- 使用
RecursiveTreeView
组件来展示树结构。 nodes
属性传入树的根节点列表。nodeBuilder
属性用于自定义每个节点的渲染方式,这里使用ListTile
来显示节点标题和一个下拉图标。
- 使用
这个示例展示了如何基本使用recursive_tree_flutter
插件来渲染一个递归的树结构。你可以根据需要进一步自定义节点的渲染逻辑和交互行为。