看完此文,你一定會會驚訝於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);
},
)
複製程式碼
結語
本文到此接近尾聲了,如果想快速嚐鮮Flutter,《Flutter七日》會是你的必備佳品;如果想細細探究它,那就跟隨我的腳步,完成一次Flutter之旅。
另外本人有一個Flutter微信交流群,歡迎小夥伴加入,共同探討Flutter的問題,本人微訊號:zdl1994328
,期待與你的交流與切磋。