看完此文,你一定会会惊讶于Flutter在视图方面是多么优雅
你拿之与Android原生或iOS原生相比,简直天差地别,就像蒸汽时代VS电器时代
下面就是四十行代码能够发挥出的威力,其中每个文字都可以替换成任意组件,Flutter(颤抖)吧!
1.TreeWidget的思路
以前Android原生,跟过鸿阳的视频做过类似的树状效果,当时还是小白,听得云里雾里,还好最后实现了。
既然Flutter的视图如此强大,那到底能有多强大,组件的复用如何秒杀原生视图
对于这个树状组件,开始设计时我也很头疼,也走错了路,想一下将所有节点显示,然后控制显隐
然未果,可以说山重水复疑无路,柳暗花明又一村。灵光一现,组件不就是用来拼合的吗?
于是我不再注重一统全局,而是化整为零,各个击破。结果证明这样是对的。
1.1:Node对象
这是最初设计时就意识到的,我必须通过一个对象去控制节点,
这个Node中记录自身Widget和它内部的若干Node,记住是Node!!!
///记录节点信息的Node类 class Node { Widget me;//节点自身Widget List<Node> children;//节点所包含的Node Node({this.me, this.children}); }
1.2:NodeWidget组件对象
NodeWidget的功能是展示一个Node节点,点击时可以将子Node展示出来,再点击收拢Node
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; } } }
1.3:NodeWidget的使用
这样化万为一,再由一聚万。看似无用,却变幻无穷,妙哉,妙哉。
var friendsNode=[Node(me: Text("张三丰")),Node(me: Text("独孤九剑")),Node(me: Text("令狐冲")),Node(me: Text("魏无羡"))]; var node = Node(me: Text("我的好友",), children: [ Node(me: NodeWidget(node: Node(me: Text("损友",), children: friendsNode))), Node(me: Text("好友")), Node(me: Text("道友",)), Node(me: Text("漫友",)), Node(me: Text("普友",)), ]); var show = NodeWidget(node: node,);
2.TextTreeWidget的封装
上面在使用上有一点点麻烦,所以简单加个箭头图标再封装一下。
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 ] ); } }
使用
感觉这是在封装结构,而不是封装组件,可以将组件和结构进行抽离,这样拓展性会非常好。
感觉这里不是最好的状态,以后有时间再重构这四十行代码吧。
var node = Node(me: Text("我的好友"), children: [ Node(me: TextTreeWidget.fromStr("损友",["张三丰","独孤九剑","令狐冲","魏无羡"])), Node(me: TextTreeWidget.fromStr("好友",["西施","杨玉环","王昭君","貂蝉"])), Node(me: Text("道友",)), Node(me: Text("漫友",)), Node(me: Text("普友",)),]); var show = TextTreeWidget( node: node, onClickCallback: (closed) { print(closed); }, )
点击查看更多内容
1人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦