Text("billy")
.intoExpanded(flex: 1)
.intoContainer(color: Colors.white)
有些widget有多个子widget (children), 可以添加如下的扩展函数:
extension WidgetExt on Widget {
//添加一个相邻的widget,返回List<Widget>
List<Widget> addNeighbor(Widget widget) {
return <Widget>[this, widget];
}
//添加各种单child的widget容器
//如:Container、Padding等...
}
extension WidgetListExt<T extends Widget> on List<T> {
//子List<Widget>列表中再添加一个相邻的widget,并返回当前列表
List<Widget> addNeighbor(Widget widget) {
return this..add(widget);
}
Row intoRow({
Key key,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
MainAxisSize mainAxisSize = MainAxisSize.max,
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
TextDirection textDirection,
VerticalDirection verticalDirection = VerticalDirection.down,
TextBaseline textBaseline,
}) {
return Row(
key: key,
mainAxisAlignment: mainAxisAlignment,
mainAxisSize: mainAxisSize,
crossAxisAlignment: crossAxisAlignment,
textDirection: textDirection,
verticalDirection: verticalDirection,
textBaseline: textBaseline,
children: this,
);
}
//添加其它多child的widget容器
//如:Column、ListView等...
}
[](
)使用扩展函数解决嵌套过深的问题
回到本文最初的嵌套地狱,现在我们的代码可以写成这样
class Test extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Demo'),),
body: buildItem("amy")
.addNeighbor(buildItem("billy"),)
.intoListView()
.intoOffstage(offstage: false)
.intoContainer()
);
}
Container buildItem(String name) {
return Icon(Icons.phone)
.addNeighbor(Text(name))
.intoRow(crossAxisAlignment: CrossAxisAlignment.center,)
.intoContainer(color: Colors.white, padding: EdgeInsets.all(20),);
}
}
为了让我们的代码更加符合链式编程风格,再定义一个静态方法吧
class WidgetChain {
static Widget addNeighbor(Widget widget) {
return widget;
}
}
另外,再定义一个从数据到widget的映射扩展方法
extension ListExt<T> on List<T> {
List<Widget> buildAllAsWidget(Widget Function(T) builder) {
return this.map<Widget>((item) {
return builder(item);
}).toList();
}
}
现在,代码是这样的:
class Test extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Demo'),),
body: ["amy", "billy"]
.buildAllAsWidget((name) =>
WidgetChain
.addNeighbor(Icon(Icons.phone))
.addNeighbor(Text(name))
.intoRow(crossAxisAlignment: CrossAxisAlignment.center,)
.intoContainer(color: Colors.white, padding: EdgeInsets.all(20),)
)
.intoListView()
.intoOffstage(offstage: false)
.intoContainer()
);
}
}
值得指出的是,扩展函数(无嵌套)跟构造函数(有嵌套)是可以混用的。上面的代码也可以写成这样(Container
和Offstage
这2层改成了构造函数):
class Test extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Demo'),),
body: Container(
child: Offstage(
offstage: false,
child: ["amy", "billy"]
.buildAllAsWidget((name) =>
WidgetChain
.addNeighbor(Icon(Icons.phone))
.addNeighbor(Text(name))
.intoRow(crossAxisAlignment: CrossAxisAlignment.center,)
.intoContainer(color: Colors.white, padding: EdgeInsets.all(20),)
)
.intoListView()
),
),
);
}
}
这样的扩展函数你想不想试试呢?我已经替大家封装好了常用Widget对应的into扩展函数,可以直接食用:
dependencies:
widget_chain: ^0.1.0
导入:
import 'package:widget_chain/widget_chain.dart';
然后就可以起飞了!
Github源码地址: [widget_chain](
) 【就算你现在用不上,也可以先star收藏之,今后如果有人向你吐槽flutter嵌套深,除了叫他拆分封装之外,还可以把widget_chain甩给他 ?? 】
[](
)总结
本文介绍了Flutter中的嵌套地狱,并使用扩展函数的方式来解决flutter的嵌套地狱问题。
由于大篇幅的扩展函数调用会影响代码的阅读体验(因为intoXxx
函数的调用顺序与widget层级是相反的),需要保留关键嵌套层级结构以使得布局的层级结构保持清晰,文中的扩展函数支持与构造函数混用,具体使用到什么程度,就看大家自己的选择了
[](
)2019-12-30编辑后补充说明
本文初次发布时包含了使用扩展函数提升编码体验的相关内容。因为我之前编写flutter代码时添加父容器的方式为:
-
先剪切要添加父容器的widget代码
-
在剪切处编写父容器及其属性
- 在父容器节点下添加child,粘贴刚才剪切的内容作为child的值
原创文章,作者:kepupublish,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/148614.html