Flutter开发中,SliverFloatingHeader是专门用于简化浮动头部的实现,它的作用是响应用户的滚动方向来控制头部组件的显示与隐藏,简单总结如下:
API:
FloatingHeaderSnapMode.overlay:当向下滑动触发头部展开时,头部会像浮层一样直接覆盖在列表内容的上方。
FloatingHeaderSnapMode.scroll:适合不需要改变列表滚动位置的悬浮组件。例如,应用首页的搜索栏或悬浮操作按钮。
场景:
1 应用首页搜索栏
2 新闻应用标题栏
栗子:
class Demo extends StatelessWidget {
const Demo ({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("浮动卡片区域")),
body: CustomScrollView(
slivers: [
SliverFloatingHeader(
animationStyle: AnimationStyle(
duration: const Duration(milliseconds: 220),
curve: Curves.easeOut,
),
snapMode: FloatingHeaderSnapMode.overlay,
child: Container(
margin: const EdgeInsets.all(12),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.blueAccent.shade100,
borderRadius: BorderRadius.circular(10),
),
child: const Text(
"浮动展示卡片:拖动滚动会触发吸附动画",
style: TextStyle(fontSize: 16),
),
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => ListTile(
leading: const Icon(Icons.inventory_2),
title: Text("商品条目 ${index + 1}"),
subtitle: Text("条目详情描述 ${index + 1}"),
),
childCount: 35,
),
),
],
),
),
);
}
}
class StickyHeaderDelegate extends SliverPersistentHeaderDelegate {
final Widget content;
final double height;
StickyHeaderDelegate({required this.content, required this.height});
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) => content;
@override
double get maxExtent => height;
@override
double get minExtent => height;
@override
bool shouldRebuild(covariant StickyHeaderDelegate oldDelegate) => oldDelegate.content != content;
}
class TestDemo extends StatelessWidget {
const TestDemo ({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("多模块滚动布局")),
body: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Container(
height: 130,
width: double.infinity,
color: Colors.orangeAccent,
alignment: Alignment.center,
child: const Text("首页活动横幅", style: TextStyle(fontSize: 22, color: Colors.white)),
),
),
// 浮动公告卡片
SliverFloatingHeader(
animationStyle: AnimationStyle(
duration: const Duration(milliseconds: 280),
curve: Curves.easeInOutCubic,
),
snapMode: FloatingHeaderSnapMode.scroll,
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
padding: const EdgeInsets.all(14),
decoration: BoxDecoration(
color: Colors.indigo.shade50,
borderRadius: BorderRadius.circular(8),
),
child: const Text("限时公告:全场数码商品满减活动开启"),
),
),
// 第一层常驻吸顶栏
SliverPersistentHeader(
pinned: true,
delegate: StickyHeaderDelegate(
height: 46,
content: Container(
color: Colors.teal,
alignment: Alignment.centerLeft,
padding: const EdgeInsets.only(left: 16),
child: const Text("一级分类:数码专区", style: TextStyle(color: Colors.white)),
),
),
),
SliverPersistentHeader(
pinned: true,
delegate: StickyHeaderDelegate(
height: 42,
content: Container(
color: Colors.green.shade400,
alignment: Alignment.centerLeft,
padding: const EdgeInsets.only(left: 16),
child: const Text("二级分类:手机配件", style: TextStyle(color: Colors.white)),
),
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => ListTile(
title: Text("数码单品 ${index + 1}"),
trailing: Text("¥${99 + index * 20}"),
),
childCount: 50,
),
),
],
),
),
);
}
}
注意:
1 必须配合CustomScrollView
2 避免嵌套滚动视图 确保所有的Sliver组件都在同一个CustomScrollView中,避免嵌套多个滚动视图导致滚动冲突问题。

2554

被折叠的 条评论
为什么被折叠?



