Flutter树状视图展示插件list_treeview的使用
Flutter树状视图展示插件list_treeview
的使用
简介
list_treeview
是一个基于Flutter ListView
实现的树状视图插件,具有高度可定制性、高效性能以及支持无限层级子节点的特点。它只管理数据的树结构,UI由用户自行设计。
主要特性
- 高度可定制:仅管理数据的树结构,UI由开发者自定义。
- 性能高效:得益于
ListView
的复用机制。 - 支持无限层级的子节点和子节点数量。
Flutter 2.0支持
从版本 0.3.0 开始支持Flutter 2.0的空安全特性。
使用指南
安装步骤
1. 添加依赖
在pubspec.yaml
文件中添加对list_treeview
的依赖:
dependencies:
list_treeview: [version]
2. 获取包
执行以下命令安装依赖:
$ flutter pub get
3. 导入包
在需要使用的Dart文件中导入list_treeview
:
import 'package:list_treeview/list_treeview.dart';
示例代码
以下是一个完整的示例,展示了如何使用list_treeview
创建一个简单的树状视图:
import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:list_treeview/list_treeview.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
State<StatefulWidget> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Home')),
body: Center(
child: ElevatedButton(
child: Text('TreeView'),
onPressed: () {
Navigator.push(context, CupertinoPageRoute(builder: (_) => TreePage()));
},
),
),
);
}
}
/// 数据绑定类
class TreeNodeData extends NodeData {
TreeNodeData({this.label, this.color}) : super();
final String? label;
final Color? color;
String? property1;
String? property2;
String? property3;
}
class TreePage extends StatefulWidget {
@override
State<StatefulWidget> createState() => _TreePageState();
}
class _TreePageState extends State<TreePage> with SingleTickerProviderStateMixin {
TreeViewController? _controller;
bool _isSuccess = false;
List<Color> _colors = [];
@override
void initState() {
super.initState();
_controller = TreeViewController();
getData();
}
void getData() async {
await Future.delayed(Duration(seconds: 2));
var colors1 = TreeNodeData(label: 'Colors1');
var color11 = TreeNodeData(label: 'rgb(0,139,69)', color: Color.fromARGB(255, 0, 139, 69));
var color12 = TreeNodeData(label: 'rgb(0,139,69)', color: Color.fromARGB(255, 0, 191, 255));
var color13 = TreeNodeData(label: 'rgb(0,139,69)', color: Color.fromARGB(255, 255, 106, 106));
var color14 = TreeNodeData(label: 'rgb(0,139,69)', color: Color.fromARGB(255, 160, 32, 240));
colors1.addChild(color11);
colors1.addChild(color12);
colors1.addChild(color13);
colors1.addChild(color14);
var colors2 = TreeNodeData(label: 'Colors2');
var color21 = TreeNodeData(label: 'rgb(0,139,69)', color: Color.fromARGB(255, 255, 64, 64));
var color22 = TreeNodeData(label: 'rgb(0,139,69)', color: Color.fromARGB(255, 28, 134, 238));
var color23 = TreeNodeData(label: 'rgb(0,139,69)', color: Color.fromARGB(255, 255, 106, 106));
var color24 = TreeNodeData(label: 'rgb(0,139,69)', color: Color.fromARGB(255, 205, 198, 115));
colors2.addChild(color21);
colors2.addChild(color22);
colors2.addChild(color23);
colors2.addChild(color24);
_controller!.treeData([colors1, colors2]);
setState(() {
_isSuccess = true;
});
}
Color getColor(int level) {
return _colors[level % _colors.length];
}
Color randomColor() {
int r = Random.secure().nextInt(200);
int g = Random.secure().nextInt(200);
int b = Random.secure().nextInt(200);
return Color.fromARGB(255, r, g, b);
}
void add(TreeNodeData dataNode) {
int r = Random.secure().nextInt(255);
int g = Random.secure().nextInt(255);
int b = Random.secure().nextInt(255);
var newNode = TreeNodeData(label: 'rgb($r,$g,$b)', color: Color.fromARGB(255, r, g, b));
_controller!.insertAtFront(dataNode, newNode);
}
void delete(dynamic item) {
_controller!.removeItem(item);
}
void select(dynamic item) {
_controller!.selectItem(item);
}
void selectAllChild(dynamic item) {
_controller!.selectAllChild(item);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('TreeView')),
body: _isSuccess ? getBody() : getProgressView(),
);
}
Widget getProgressView() {
return Center(child: CircularProgressIndicator());
}
Widget getBody() {
return ListTreeView(
shrinkWrap: false,
padding: EdgeInsets.all(0),
itemBuilder: (BuildContext context, NodeData data) {
TreeNodeData item = data as TreeNodeData;
double offsetX = item.level * 16.0;
return Container(
height: 54,
padding: EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(border: Border(bottom: BorderSide(width: 1, color: Colors.grey))),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Padding(
padding: EdgeInsets.only(left: offsetX),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.only(right: 5),
child: InkWell(
splashColor: Colors.amberAccent.withOpacity(1),
highlightColor: Colors.red,
onTap: () {
selectAllChild(item);
},
child: data.isSelected
? Icon(Icons.star, size: 30, color: Color(0xFFFF7F50))
: Icon(Icons.star_border, size: 30, color: Color(0xFFFFDAB9)),
),
),
Text('level-${item.level}-${item.indexInParent}',
style: TextStyle(fontSize: 15, color: getColor(item.level))),
],
),
),
),
Visibility(
visible: item.isExpand,
child: InkWell(
onTap: () {
add(item);
},
child: Icon(Icons.add, size: 30),
),
)
],
),
);
},
onTap: (NodeData data) {
print('index = ${data.index}');
},
onLongPress: (data) {
delete(data);
},
controller: _controller,
);
}
}
功能说明
-
初始化控制器
- 在创建
TreeView
时必须初始化控制器。
_controller = TreeViewController();
- 在创建
-
设置每行的数据
- 数据类必须继承自
NodeData
,可以自定义其他属性。
class TreeNodeData extends NodeData { TreeNodeData({this.label, this.color}) : super(); final String? label; final Color? color; }
- 数据类必须继承自
-
插入节点
_controller.insertAtFront(dataNode, newNode); // 或者使用 insertAtRear 和 insertAtIndex 方法
-
删除节点
_controller.removeItem(item);
-
展开或折叠子节点
_controller.expandOrCollapse(index);
-
选择节点
- 仅选中自身:
_controller.selectItem(item);
- 选中自身及其所有子节点:
_controller.selectAllChild(item);
通过上述步骤,您可以轻松地在Flutter应用中集成并使用list_treeview
插件来展示树状视图。
更多关于Flutter树状视图展示插件list_treeview的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter树状视图展示插件list_treeview的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter中使用list_treeview
插件来展示树状视图的代码案例。首先,确保你已经在pubspec.yaml
文件中添加了list_treeview
依赖项:
dependencies:
flutter:
sdk: flutter
list_treeview: ^最新版本号 # 请替换为最新版本号
然后,运行flutter pub get
来获取依赖项。
以下是一个完整的示例代码,展示如何使用list_treeview
插件来展示一个简单的树状视图:
import 'package:flutter/material.dart';
import 'package:list_treeview/list_treeview.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter TreeView Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// 定义树状结构的数据
final List<TreeViewNode> treeData = [
TreeViewNode(
title: 'Node 1',
children: [
TreeViewNode(
title: 'Child 1.1',
),
TreeViewNode(
title: 'Child 1.2',
children: [
TreeViewNode(
title: 'Grandchild 1.2.1',
),
],
),
],
),
TreeViewNode(
title: 'Node 2',
children: [
TreeViewNode(
title: 'Child 2.1',
),
],
),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter TreeView Example'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: TreeView(
nodes: treeData,
onNodeTap: (node) {
// 当节点被点击时,执行的操作
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Tapped: ${node.title}'),
),
);
},
),
),
);
}
}
在这个示例中:
- 我们首先定义了一个包含树状结构数据的
List<TreeViewNode>
。每个TreeViewNode
可以包含子节点,形成一个递归的树状结构。 - 在
MyHomePage
的build
方法中,我们使用TreeView
小部件来展示这个树状结构。 onNodeTap
回调函数用于处理节点点击事件,这里简单地显示一个SnackBar
,显示被点击节点的标题。
这个示例展示了如何使用list_treeview
插件来展示和交互一个基本的树状视图。你可以根据实际需求,进一步自定义节点样式、增加功能等。