我正在开发一个 Flutter 项目,想要实现一个带有固定标题的 CustomScrollView。具体来说,我希望每个标题仅在完全滚动过去后才粘在屏幕顶部。在那之前,它应该保留在它所属部分的底部。
这种行为在 Flutter 中可能吗?如果是这样,实现这一目标的最佳方法是什么?
在下面的屏幕截图中,我们当前正在滚动浏览“标题 2”部分,我希望将“标题 3”和“标题 4”固定在底部。
是的,这种行为是完全可能的,但需要一些定制。
SliverAppBar 默认只能将 header 固定在顶部,所以要实现这种“上下固定”的效果,需要结合使用 CustomScrollView、SliverPercientHeader 以及一些自定义逻辑来控制标头的行为方式。
以下是如何实现此目标的基本示例:
class MyPinnedHeaders extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: [
// Header 1 - Pinned to the top
SliverPersistentHeader(
pinned: true,
delegate: _HeaderDelegate(
minHeight: 50,
maxHeight: 150,
child: Container(
color: Colors.red,
child: Center(child: Text('Header 1')),
),
),
),
// Content under Header 1
SliverToBoxAdapter(
child: Container(height: 200, color: Colors.green, child: Text('Item 3')),
),
// Header 2 - Pinned to the top
SliverPersistentHeader(
pinned: true,
delegate: _HeaderDelegate(
minHeight: 50,
maxHeight: 150,
child: Container(
color: Colors.blue,
child: Center(child: Text('Header 2')),
),
),
),
// Content under Header 2
SliverToBoxAdapter(
child: Container(height: 200, color: Colors.green, child: Text('Item 4')),
),
],
),
);
}
}
class _HeaderDelegate extends SliverPersistentHeaderDelegate {
final double minHeight;
final double maxHeight;
final Widget child;
_HeaderDelegate({
required this.minHeight,
required this.maxHeight,
required this.child,
});
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return SizedBox.expand(child: child);
}
@override
double get maxExtent => maxHeight;
@override
double get minExtent => minHeight;
@override
bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate){
return true;
}
}
这将使您的标题在您滚动经过它们时固定在顶部。如果您希望标题也固定在部分的底部,您可以自定义 SliverPercientHeaderDelegate 通过控制标题的放置方式来实现该行为。