Flutter笔记--SliverFloatingHeader
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中,避免嵌套多个滚动视图导致滚动冲突问题。
