把数据处理成node这样的,直接调用就ok.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'Node.dart';
void main() {
runApp(new MaterialApp(
home: MyTree(),
));
}
class MyTree extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return MyTreeState();
}
}
class MyTreeState extends State<MyTree> {
List<Node> expand = new List();
///保存所有数据的List
List<Node> list = new List();
List<int> mark = new List();
@override
void initState() {
buildNode();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('tree'),
),
body: Container(
child: Column(
children: _buildNode(expand),
),
),
);
}
///构建元素
List<Widget> _buildNode(List<Node> nodes) {
print('buildNode:' + nodes.length.toString());
List<Widget> widgets = List();
if (nodes != null && nodes.length > 0) {
for (Node node in nodes) {
widgets.add(GestureDetector(
child: ImageText(10.0 * node.depth, node.object.toString(),
node.expand, node.isHasChildren),
onTap: () {
if (node.isHasChildren) {
if (node.expand) {
//之前是扩展状态,收起列表
node.expand = false;
_collect(node.nodeId);
} else {
//之前是收起状态,扩展列表
node.expand = true;
_expand(node.nodeId);
}
setState(() {});
}
},
));
}
}
return widgets;
}
///第一个节点的index
int nodeId = 1;
///扩展机构树:id代表被点击的机构id
/// 做法是遍历整个list列表,将直接挂在该机构下面的节点增加到一个临时列表中,
///然后将临时列表插入到被点击的机构下面
void _expand(int id) {
//保存到临时列表
List<Node> tmp = new List();
for (Node node in list) {
if (node.fatherId == id) {
tmp.add(node);
}
}
//找到插入点
int index = -1;
int length = expand.length;
for (int i = 0; i < length; i++) {
if (id == expand[i].nodeId) {
index = i + 1;
break;
}
}
//插入
expand.insertAll(index, tmp);
}
///收起机构树:id代表被点击的机构id
/// 做法是遍历整个expand列表,将直接和间接挂在该机构下面的节点标记,
///将这些被标记节点删除即可,此处用到的是将没有被标记的节点加入到新的列表中
void _collect(int id) {
//清楚之前的标记
mark.clear();
//标记
_mark(id);
//重新对expand赋值
List<Node> tmp = new List();
for (Node node in expand) {
if (mark.indexOf(node.nodeId) < 0) {
tmp.add(node);
} else {
node.expand = false;
}
}
expand.clear();
expand.addAll(tmp);
setState(() {});
}
///标记,在收起机构树的时候用到
void _mark(int id) {
for (Node node in expand) {
if (id == node.fatherId) {
if (node.isHasChildren) {
_mark(node.nodeId);
}
mark.add(node.nodeId);
}
}
}
void buildNode() {
Node<String> node = new Node(false, 1, 1, 0, '哈哈1', true);
Node<String> node1 = new Node(false, 1, 2, 0, '哈哈2', false);
Node<String> node2 = new Node(false, 1, 3, 0, '哈哈3', false);
Node<String> node3 = new Node(false, 1, 4, 0, '哈哈4', false);
Node<String> node4 = new Node(false, 3, 5, 1, '呵呵1', true);
Node<String> node5 = new Node(false, 6, 6, 5, 'geg2', false);
expand.add(node);
expand.add(node1);
expand.add(node2);
expand.add(node3);
list.add(node);
list.add(node1);
list.add(node2);
list.add(node3);
list.add(node4);
list.add(node5);
print('创建数据:' + expand.length.toString());
}
}
class ImageText extends StatelessWidget {
double margin = 0;
String str = '';
bool isExpand = false;
bool isHasChildren = false;
ImageText(double margin, String str, bool isExpand, bool isHasChildren) {
this.margin = margin;
this.str = str;
this.isExpand = isExpand;
this.isHasChildren = isHasChildren;
print('margin:' + margin.toString());
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Container(
alignment: Alignment.centerLeft,
decoration: BoxDecoration(color: Colors.greenAccent),
width: double.infinity,
height: 40,
margin: EdgeInsets.only(left: margin),
child: Row(
children: <Widget>[
Visibility(
visible: isHasChildren,
child: Image.asset(isExpand
? 'images/arrow_down_gray1.png'
: 'images/arrow_right_gray.png'),
),
Text(
str,
style: TextStyle(fontSize: 17),
)
],
),
);
}
}
class Node<T> {
bool expand; //是否展开
int depth; //深度
int nodeId; //id
int fatherId; //父类id
T object; //
bool isHasChildren; //是否有孩子节点
Node(this.expand, this.depth, this.nodeId, this.fatherId, this.object,
this.isHasChildren);
}