After reading this article, you will be surprised at how elegant Flutter is in view

This is what 40 lines of code can do. Each word can be replaced with any component, Flutter!

1. The TreeWidget train of thought

Before Android native, with hongyang video made a similar tree effect, at that time or small white, listen to the clouds in the fog, fortunately finally realized.

Since the Flutter view is so powerful, how powerful can it be and how to reuse components in a second? I also had a lot of headaches when I started designing this tree component. I also went the wrong way when I thought about displaying all nodes and then controlling them in and out. It was an Epiphany. Isn’t that what components are for? So I no longer pay attention to unify the whole, but break the whole into parts, each to defeat. It turned out to be right.


1.1: Node object

This was realized from the beginning of the design, that I had to control the nodes through an object,

This Node records its own widgets and the number of nodes inside it.

Class Node {Widget me; // Widget List<Node> children; Node({this.me, this.children}); }Copy the code

1.2: NodeWidget component object

The NodeWidget displays a Node, and when clicked, the child nodes are displayed, and then the Node is closed

class NodeWidget extends StatefulWidget {
  NodeWidget({Key key, this.node}) : super(key: key);
  final Node node;
  @override
  _NodeWidgetState createState() => _NodeWidgetState();
}
class _NodeWidgetState extends State<NodeWidget> {
  Node node;
  bool showList = false;
  @override
  Widget build(BuildContext context) {
    return showNode(widget.node, showList);
  }
  Widget showNode(Node node, bool show) {
    var me = InkWell(child: node.me,
        onTap: () {
          showList = !showList;
          print(showList);
          setState(() {});});
    if (show) {
      var children = Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: node.children.map((node) => node.me).toList(),);
      return Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[me,
          Padding(padding: EdgeInsets.only(left: 20),
            child: children,)],);
    } else {
      return me;
    }
  }
}
Copy the code

The use of 1.3: NodeWidget

In this way we make all one, and from one we make all ten. Seemingly useless, but endless changes, wonderful, wonderful.

Var friendsNode = [Node (me: Text (" zhang sanfeng ")), the Node (me: Text (" lonely nine swords ")), the Node (me: Text (" linghu chong ")), the Node (me: Text (" wei without envy "))); Var node = node (me: Text(" mY friend ",), children: [node (me: NodeWidget(node: me: Text(" my friend ",), children: [node (me: NodeWidget(node: node (me: Text(" my friend ",), children: FriendsNode))), the Node (me: Text (" friends ")), the Node (me: Text (" friends ",)), the Node (me: Text (" random friends, ")), the Node (me: Text (" PuYou, ")),]); var show = NodeWidget(node: node,);Copy the code

2. TextTreeWidget encapsulation

The above is a little bit troublesome to use, so simply add an arrow icon and encapsulate it.

class TextTreeWidget extends StatefulWidget { TextTreeWidget({Key key, this.node, this.onClickCallback}) : super(key: key); final Node node; final OnClickCallback onClickCallback; factory TextTreeWidget.fromStr(String me,List<String> children){ return TextTreeWidget(node: Node(me: Text(me),children: children.map((e)=>Node(me: Text(e))).toList } @override _TextTreeWidgetState createState() => _TextTreeWidgetState(); } class _TextTreeWidgetState extends State<TextTreeWidget> { Node node; bool showList = false; @override Widget build(BuildContext context) { return showNode(widget.node, showList); } Widget showNode(Node node, bool show) { var me = InkWell( child: formWidget(node.me), onTap: () { showList = ! showList; if (widget.onClickCallback ! = null) { widget.onClickCallback(! showList); } setState(() {}); }); if (show) { var children = Column( crossAxisAlignment: CrossAxisAlignment.start, children: node.children.map((node) => node.me).toList(), ); return Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: <Widget>[ me, Padding(padding: EdgeInsets.only(left: 30),child: children,], ); } else {return me; } } Widget formWidget(Widget me) { return Row(crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[ Transform.rotate( angle: !showList ? 0 : 90 / 180 * pi, child: Icon(Icons.arrow_right), ), me ] ); }}Copy the code

use

It feels like you’re encapsulating the structure, not the component, and you can separate the component from the structure, so it’s very extensible.

I don’t think this is the best situation, so I’ll refactor those 40 lines later.

Var node = node (me: Text(" mY friend "), children: [node (me: TextTreeWidget. FromStr (" false friends ", "zhang sanfeng", "lonely nine swords", "no", "wei without envy"])), the Node (me: TextTreeWidget. FromStr (" friends ", "beauty", "the jade bracelet", "wang zhaojun", "the sable cicada"])), the Node (me: Text (" friends ",)), the Node (me: Text (" random friends, ")), the Node (me: The Text (" PuYou ",)),]); var show = TextTreeWidget( node: node, onClickCallback: (closed) { print(closed); },)Copy the code

conclusion

This is the end of this article. If you want to taste Flutter quickly, Flutter For Seven days is a must-have. If you want to explore it, follow in my footsteps and complete a Flutter tour. In addition, I have a Flutter wechat communication group. You are welcome to join and discuss Flutter issues together. My wechat account is ZDL1994328.