带有动态列表的 Flutter 自定义滚动
Flutter custom scrolling with dynamic list
有关于 flutter 的问题 CustomScrollView
我现在拥有的是:
@override
Widget build(BuildContext context) {
return Container(
child: CustomScrollView(
shrinkWrap: true,
slivers: <Widget>[
SliverPadding(
padding: EdgeInsets.all(0),
sliver: SliverList(
delegate: SliverChildListDelegate(
<Widget>[
Card(),
Card(),
Container(
child: ListView.builder(
physics: const NeverScrollableScrollPhysics(),
),
)
],
),
),
),
],
),
);
}
*代码已简化,因为它是示例。
如您所见,里面有 2 个 Cards()
和一个 Container
,里面有 ListView
。两张卡片都有固定高度,带列表的容器有动态高度。
现在是如何工作的:随着 ListView 的长大,我们可以滚动到列表的底部。所以通常 Card
小部件都变得不可见,因为 List
的元素占据了所有屏幕。
这个想法是强制第二个 Card()
固定在屏幕顶部。所以基本上它应该在它自己的位置,但是随着越来越多的滚动,当我越来越多地滚动列表时它应该被固定到屏幕的顶部。
问题是我怎样才能做这样的事情?
谢谢!
您可以使用 SliverPersistentHeader
,我为您准备了这个样本:
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: CustomScrollView(
slivers: <Widget>[
SliverPadding(
padding: EdgeInsets.all(0),
sliver: SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
return ListTile(
title: Text("index: $index"),
);
},
childCount: 3,
)),
),
SliverPersistentHeader(
pinned: true,
delegate: PersistentHeader("Card 1"),
),
SliverPersistentHeader(
pinned: true,
delegate: PersistentHeader("Card 2"),
),
SliverPadding(
padding: EdgeInsets.all(0),
sliver: SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
return ListTile(
title: Text("index: $index"),
);
})),
),
],
),
),
);
}
}
class PersistentHeader extends SliverPersistentHeaderDelegate {
final String title;
PersistentHeader(this.title);
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return Container(
color: Colors.white,
child: Card(
color: Colors.white,
elevation: 7.0,
child: SizedBox(height: 100.0, child: Center(child: Text(title))),
),
);
}
@override
double get maxExtent => 100.0;
@override
double get minExtent => 100.0;
@override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
return false;
}
}
更多信息:https://docs.flutter.io/flutter/widgets/SliverPersistentHeader-class.html
有关于 flutter 的问题 CustomScrollView
我现在拥有的是:
@override
Widget build(BuildContext context) {
return Container(
child: CustomScrollView(
shrinkWrap: true,
slivers: <Widget>[
SliverPadding(
padding: EdgeInsets.all(0),
sliver: SliverList(
delegate: SliverChildListDelegate(
<Widget>[
Card(),
Card(),
Container(
child: ListView.builder(
physics: const NeverScrollableScrollPhysics(),
),
)
],
),
),
),
],
),
);
}
*代码已简化,因为它是示例。
如您所见,里面有 2 个 Cards()
和一个 Container
,里面有 ListView
。两张卡片都有固定高度,带列表的容器有动态高度。
现在是如何工作的:随着 ListView 的长大,我们可以滚动到列表的底部。所以通常 Card
小部件都变得不可见,因为 List
的元素占据了所有屏幕。
这个想法是强制第二个 Card()
固定在屏幕顶部。所以基本上它应该在它自己的位置,但是随着越来越多的滚动,当我越来越多地滚动列表时它应该被固定到屏幕的顶部。
问题是我怎样才能做这样的事情?
谢谢!
您可以使用 SliverPersistentHeader
,我为您准备了这个样本:
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: CustomScrollView(
slivers: <Widget>[
SliverPadding(
padding: EdgeInsets.all(0),
sliver: SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
return ListTile(
title: Text("index: $index"),
);
},
childCount: 3,
)),
),
SliverPersistentHeader(
pinned: true,
delegate: PersistentHeader("Card 1"),
),
SliverPersistentHeader(
pinned: true,
delegate: PersistentHeader("Card 2"),
),
SliverPadding(
padding: EdgeInsets.all(0),
sliver: SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
return ListTile(
title: Text("index: $index"),
);
})),
),
],
),
),
);
}
}
class PersistentHeader extends SliverPersistentHeaderDelegate {
final String title;
PersistentHeader(this.title);
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return Container(
color: Colors.white,
child: Card(
color: Colors.white,
elevation: 7.0,
child: SizedBox(height: 100.0, child: Center(child: Text(title))),
),
);
}
@override
double get maxExtent => 100.0;
@override
double get minExtent => 100.0;
@override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
return false;
}
}
更多信息:https://docs.flutter.io/flutter/widgets/SliverPersistentHeader-class.html