如何在Flutter的Cupertino导航栏内实现可折叠Silver SearchBar?
实现Cupertino风格可折叠搜索栏方案
我刚好做过类似的需求,核心思路是用SliverAppBar配合Cupertino组件来模拟iOS原生的折叠效果——因为原生CupertinoNavigationBar并非Sliver组件,没法直接和Sliver列表联动实现滚动折叠。下面是完整的可运行代码,以及关键细节的解释:
import 'package:flutter/cupertino.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return const CupertinoApp( title: 'Collapsible Search Demo', home: CollapsibleSearchScreen(), ); } } class CollapsibleSearchScreen extends StatefulWidget { const CollapsibleSearchScreen({super.key}); @override State<CollapsibleSearchScreen> createState() => _CollapsibleSearchScreenState(); } class _CollapsibleSearchScreenState extends State<CollapsibleSearchScreen> { final ScrollController _scrollController = ScrollController(); double _collapseRatio = 0.0; // 折叠比例,0=完全展开,1=完全折叠 @override void initState() { super.initState(); _scrollController.addListener(_updateCollapseState); } void _updateCollapseState() { // 计算折叠比例:当滚动偏移超过80时,完全折叠 setState(() { _collapseRatio = (_scrollController.offset / 80).clamp(0.0, 1.0); }); } @override void dispose() { _scrollController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return CupertinoPageScaffold( child: CustomScrollView( controller: _scrollController, slivers: [ // 自定义可折叠Cupertino导航栏 SliverAppBar( backgroundColor: CupertinoTheme.of(context).scaffoldBackgroundColor, pinned: true, // 保持导航栏固定在顶部 expandedHeight: 124, // 展开总高度:导航栏(44)+搜索栏(80) collapsedHeight: 44, // 折叠后高度=标准导航栏高度 leading: const CupertinoNavigationBarBackButton(), title: AnimatedOpacity( opacity: _collapseRatio, duration: const Duration(milliseconds: 150), child: const Text('Contacts'), ), actions: [ AnimatedOpacity( opacity: _collapseRatio, duration: const Duration(milliseconds: 150), child: CupertinoButton( padding: EdgeInsets.zero, child: const Icon(CupertinoIcons.search), onPressed: () { // 点击搜索按钮,滚动回顶部展开搜索栏 _scrollController.animateTo( 0, duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, ); }, ), ), ], flexibleSpace: FlexibleSpaceBar( background: Padding( padding: const EdgeInsets.only( top: 44, // 留出顶部导航栏的高度 left: 16, right: 16, bottom: 8, ), child: AnimatedOpacity( opacity: 1 - _collapseRatio, duration: const Duration(milliseconds: 150), child: CupertinoSearchTextField( placeholder: 'Search contacts', style: TextStyle( color: CupertinoTheme.of(context).textTheme.textStyle.color, ), prefixIcon: const Icon(CupertinoIcons.search), suffixIcon: const Icon(CupertinoIcons.xmark_circle_fill), ), ), ), ), ), // 示例列表内容 SliverList( delegate: SliverChildBuilderDelegate( (context, index) { return CupertinoListTile( title: Text('Contact $index'), leading: const CircleAvatar( child: Icon(CupertinoIcons.person), ), ); }, childCount: 50, ), ), ], ), ); } }
关键细节说明:
- 滚动监听与折叠比例:通过
ScrollController监听滚动偏移,计算_collapseRatio来控制UI的渐变切换,让折叠过程更平滑。 - SliverAppBar配置:
pinned: true确保导航栏始终固定在顶部;expandedHeight和collapsedHeight分别定义展开/折叠后的总高度。 - Cupertino风格一致性:使用
CupertinoSearchTextField、CupertinoNavigationBarBackButton等原生组件,保持iOS设计语言统一。 - 交互优化:折叠后显示搜索按钮,点击可快速回到顶部展开搜索栏,符合用户操作习惯。
内容的提问来源于stack exchange,提问作者Nicholas Jela
相关产品推荐
相关产品推荐

