Flutter可扩展树形菜单插件expandable_tree_menu的使用
Flutter可扩展树形菜单插件expandable_tree_menu的使用
expandable_tree_menu
是一个用于构建可展开/折叠子菜单树的Flutter插件,每个节点可以递归地包含另一个树,使用“节点”的递归列表。以下是该插件的详细使用说明。
插件简介
通过 expandable_tree_menu
插件,您可以轻松创建一个树形结构的菜单,其中每个节点都可以根据需要展开或折叠其子节点。插件支持自定义节点样式、初始展开状态、图标位置和颜色等配置选项,并提供了灵活的回调接口来处理节点选择事件。
主要特性
- 支持无限层级的树形结构
- 自定义节点渲染器(
nodeBuilder
) - 提供节点选择事件处理器(
onSelect
) - 内置多种样式配置选项
配置选项
以下是 ExpandableTree
组件提供的主要配置项:
initiallyExpanded
: 是否初始状态下全部节点都处于展开状态,默认为折叠。twistyPosition
: 展开/折叠图标的相对位置,默认在右侧(TwistyPosition.after
)。openTwistyColor
: 子节点已展开时使用的图标颜色,默认基于主题色。closedTwistyColor
: 子节点未展开时使用的图标颜色,默认基于主题色。openTwisty
: 已展开时显示的自定义小部件,默认为Icons.expand_less
。closedTwisty
: 未展开时显示的自定义小部件,默认为Icons.expand_more
。childIndent
: 子节点相对于父节点缩进的距离,默认为28像素。submenuDecoration
: 包含子节点的子菜单装饰,默认无。childrenDecoration
: 子节点本身的装饰,默认无。childrenMargin
: 子节点周围的边距,默认无。submenuMargin
: 子菜单周围的边距,默认无。submenuClosedColor
: 子菜单关闭时的颜色,默认无。submenuOpenColor
: 子菜单打开时的颜色,默认无。
基本用法
下面是一个简单的例子,展示了如何使用 ExpandableTree
创建一个多级分类菜单:
ExpandableTree(
nodes: [
TreeNode('Category A',
subNodes: [
TreeNode('CatA first item'),
TreeNode('CatA second item'),
],
),
TreeNode('Category B',
subNodes: [
TreeNode('Cat B first item'),
TreeNode('Cat B sub-category 1',
subNodes: [
TreeNode('Cat B1 first item'),
TreeNode('Cat B1 second item'),
TreeNode('Cat B1 third item'),
TreeNode('Cat B1 final item'),
],
),
],
),
],
nodeBuilder: (context, nodeValue) => Card(
child: Text(nodeValue.toString()),
),
onSelect: (node) => _nodeSelected(context, node),
)
完整示例代码
为了更好地理解插件的工作原理,这里提供了一个完整的示例应用,包括数据加载、页面跳转等功能。
import 'package:expandable_tree_menu/expandable_tree_menu.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Getting Started',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final nodes = <TreeNode>[];
void _addData(data) {
setState(() {
nodes.addAll(data);
});
}
Future<List<TreeNode>> fetchData() async {
// 模拟从服务器或其他地方获取数据
await Future.delayed(Duration(seconds: 1));
return _dataLoad();
}
@override
void initState() {
super.initState();
fetchData().then(_addData);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Menu demo'),
),
body: Column(
children: [
Flexible(
child: SingleChildScrollView(
child: ExpandableTree(
nodes: nodes,
nodeBuilder: _nodeBuilder,
onSelect: (node) => _nodeSelected(context, node),
),
),
),
],
),
);
}
/// 处理节点点击事件
void _nodeSelected(BuildContext context, nodeValue) {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => DetailPage(value: nodeValue),
));
}
/// 构建节点UI
Widget _nodeBuilder(BuildContext context, nodeValue) {
return Card(
margin: EdgeInsets.symmetric(vertical: 1),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(nodeValue.toString()),
),
);
}
}
// 详情页组件
class DetailPage extends StatelessWidget {
final value;
const DetailPage({Key? key, this.value}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(value.toString()),
),
body: Center(
child: Text(value.toString()),
),
);
}
}
// 模拟的数据加载函数
Future<List<TreeNode>> _dataLoad() async {
// 实际开发中应替换为真正的数据源
return [
TreeNode<String>('Some String'),
TreeNode<String>('Node with sub-items', subNodes: [
TreeNode<String>('First sub node'),
TreeNode<String>('Second sub node'),
])
];
}
这个例子演示了如何结合 ExpandableTree
和路由导航来实现一个交互式的树形菜单。希望这能帮助您快速上手并充分利用 expandable_tree_menu
插件!如果有任何问题或建议,请随时留言交流。
更多关于Flutter可扩展树形菜单插件expandable_tree_menu的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter可扩展树形菜单插件expandable_tree_menu的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用expandable_tree_menu
插件来创建一个可扩展的树形菜单的示例代码。
首先,确保你已经在pubspec.yaml
文件中添加了expandable_tree_menu
依赖:
dependencies:
flutter:
sdk: flutter
expandable_tree_menu: ^最新版本号 # 请替换为当前最新版本号
然后运行flutter pub get
来获取依赖。
接下来,在你的Dart文件中,你可以按照以下步骤来创建树形菜单:
import 'package:flutter/material.dart';
import 'package:expandable_tree_menu/expandable_tree_menu.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Expandable Tree Menu Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text('Expandable Tree Menu Demo'),
),
body: TreeMenuWidget(),
),
);
}
}
class TreeMenuWidget extends StatefulWidget {
@override
_TreeMenuWidgetState createState() => _TreeMenuWidgetState();
}
class _TreeMenuWidgetState extends State<TreeMenuWidget> {
// 定义树形菜单的数据结构
final List<TreeNode> treeData = [
TreeNode(
title: 'Node 1',
children: [
TreeNode(
title: 'Node 1.1',
children: [
TreeNode(title: 'Node 1.1.1'),
TreeNode(title: 'Node 1.1.2'),
],
),
TreeNode(title: 'Node 1.2'),
],
),
TreeNode(
title: 'Node 2',
children: [
TreeNode(title: 'Node 2.1'),
TreeNode(title: 'Node 2.2'),
],
),
];
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: ExpandableTreeMenu(
treeData: treeData,
onNodeTap: (TreeNode node) {
// 节点点击事件处理
print('Node tapped: ${node.title}');
},
leading: const Icon(Icons.arrow_drop_down),
trailing: const Icon(Icons.chevron_right),
),
);
}
}
// TreeNode 类定义(假设expandable_tree_menu插件没有自带此类)
class TreeNode {
final String title;
final List<TreeNode>? children;
TreeNode({required this.title, this.children});
}
在这个示例中,我们定义了一个简单的树形菜单数据结构TreeNode
,它包含一个标题和一个可选的子节点列表。然后,我们在TreeMenuWidget
中使用ExpandableTreeMenu
组件来渲染这个树形菜单。
注意:
ExpandableTreeMenu
组件接受一个treeData
参数,它是一个TreeNode
对象的列表。onNodeTap
回调函数在节点被点击时触发,这里我们只是简单地打印了被点击的节点的标题。leading
和trailing
参数分别定义了节点展开/收起图标和右侧图标,这里我们使用了Flutter的内置图标。
请确保expandable_tree_menu
插件的实际用法和API与示例代码一致,因为插件的API可能会随着版本更新而发生变化。如果遇到问题,请查阅插件的官方文档或GitHub仓库。