为避免不必要的重复,您可以将补间逻辑移动到自定义小部件。
您还可以将List<Widget> children 与List<double> gaps 与自定义Gap 小部件融合在一起。
最终您可以通过separated 构造函数继续使用ListView,并使用我们自定义的Gap 作为分隔符。
考虑到所有这些,最终您的Gap 小部件只是一个具有自定义高度的AnimatedContainer:
class Gap extends StatelessWidget {
final double gap;
const Gap(this.gap, {Key key})
: assert(gap >= .0),
super(key: key);
@override
Widget build(BuildContext context) {
return AnimatedContainer(
duration: const Duration(milliseconds: 250),
curve: Curves.easeOut,
height: gap,
);
}
}
然后您可以通过以下方式使用它:
ListView.separated(
itemCount: 42,
addAutomaticKeepAlives: true,
itemBuilder: (context, index) {
return RaisedButton(onPressed: null, child: Text("Foo $index"));
},
separatorBuilder: (context, index) {
return Gap(10.0);
},
),
这里的addAutomaticKeppAlives: true 用于确保离开然后重新出现的项目不会重置其动画。但这不是必需品。
这是一个动态改变间隙大小的完整示例:
class Home extends StatefulWidget {
@override
HomeState createState() {
return new HomeState();
}
}
class HomeState extends State<Home> {
final rand = Random.secure();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: <Widget>[
RaisedButton(
onPressed: () {
setState(() {});
},
child: Text("Reroll random gaps"),
),
Expanded(
child: ListView.separated(
addAutomaticKeepAlives: true,
itemCount: 42,
itemBuilder: (context, index) {
print("Bar");
return RaisedButton(onPressed: () {}, child: Text("Foo $index"));
},
separatorBuilder: (context, index) {
print("Foo $index");
return Gap(rand.nextDouble() * 10.0);
},
),
),
],
),
);
}
}