有时候在一个滚动页面里面会显示各种复杂的内容,并非一个单一列表。
比如这个页面在一个有序列表上方有一个输入框,并且用标题分割开
那么ListVew
组件不再适用,这时候需要使用Flutter提供的CustomScrollView
,各种系统滚动组件都是基于这个做的,它的必要参数是
final List<Widget> slivers;
,这里有个小坑就是它的内部元素不是任意Widget
,比如你直接添加Text()
进入是会报错的,一般Widget可以用SliverToBoxAdapter
包装一下,特殊的Padding
有SliverPadding
、List
有SliverList
。
这里不再一一列举,重点说一下使用有序列表的重要参数delegate
,如果你不知道怎么写,可以直接去看系统ListView.builder
,ListView.separated
,都实现这个代理。
最后演示我上面这个例子的主要代码
@override
Widget build(BuildContext context) {
int itemCount = 6;
SliverChildBuilderDelegate childrenDelegate = SliverChildBuilderDelegate(
(context, index) {
final int itemIndex = index ~/ 2;
final Widget? widget;
if (index.isEven) {
widget = Container(
alignment: AlignmentDirectional.center,
child: Text("$itemIndex"),
);
} else {
widget = Container(
height: 16.w,
decoration: BoxDecoration(
border: Border(top: BorderSide(color: AppColors.grey_color100, width: 1.w))
),
);
assert(() {
if (widget == null) {
throw FlutterError('separatorBuilder cannot return null.');
}
return true;
}());
}
return widget;
},
childCount: max(0, itemCount * 2 - 1),
addAutomaticKeepAlives: true,
addRepaintBoundaries: true,
addSemanticIndexes: true,
);
return Scaffold(
appBar: AppBar(),
body: Padding(
padding: EdgeInsets.symmetric(horizontal: 16.w),
child: CustomScrollView(
slivers: [
SliverPadding(padding: EdgeInsets.only(bottom: 16.w)),
SliverToBoxAdapter(
child: title("自定义评分体验"),
),
SliverToBoxAdapter(
child: inputView(),
),
SliverToBoxAdapter(
child: title("选择纬度(3~6个)"),
),
SliverList(delegate: childrenDelegate),
SliverPadding(padding: EdgeInsets.only(bottom: 16.w)),
],
),
),
);
}
Widget title(String text) {
return Text(
text,
style: AppTextStyles.body2_12_Regular.color_font_color_secondary,
);
}
Widget inputView() {
return TextField();
}