You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:18:05