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

Flutter开发:如何实现滚动时自动隐藏NavBar的功能

实现滚动时NavBar自动隐藏的方案

要实现滚动时NavBar自动隐藏/显示的交互,核心思路是监听页面滚动事件,根据滚动方向控制NavBar的显示状态,并添加过渡动画提升体验。以下是针对你的代码的具体修改步骤:

1. 添加状态变量与动画控制器

在_MainPageState中添加用于记录滚动位置、NavBar显示状态的变量,以及控制动画的AnimationController(需要混入SingleTickerProviderStateMixin):

class _MainPageState extends State<MainPage> with SingleTickerProviderStateMixin {
  double _previousScrollY = 0;
  bool _isNavBarVisible = true;
  late AnimationController _animationController;

  @override
  void initState() {
    super.initState();
    // 初始化动画控制器,控制显示/隐藏的过渡时长
    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 300),
    );
  }

  @override
  void dispose() {
    // 销毁控制器防止内存泄漏
    _animationController.dispose();
    super.dispose();
  }
  
  // 原build方法...
}

2. 监听滚动事件并添加动画过渡

用NotificationListener包裹页面的Stack,监听全局滚动事件,同时用SlideTransition给NavBar添加平滑的显示/隐藏动画:

@override
Widget build(BuildContext context) {
  App.init(context);
  final drawerProvider = Provider.of<DrawerProvider>(context);

  return Scaffold(
    key: drawerProvider.key,
    extendBodyBehindAppBar: true,
    drawer: !Responsive.isDesktop(context) ? const _MobileDrawer() : null,
    body: SafeArea(
      // 包裹NotificationListener监听全局滚动
      child: NotificationListener<ScrollNotification>(
        onNotification: (notification) {
          final currentScrollY = notification.metrics.pixels;
          
          // 向下滚动超过60px时隐藏NavBar
          if (currentScrollY > _previousScrollY && currentScrollY > 60) {
            if (_isNavBarVisible) {
              setState(() {
                _isNavBarVisible = false;
                _animationController.forward(); // 执行隐藏动画
              });
            }
          } 
          // 向上滚动超过20px时显示NavBar
          else if (currentScrollY < _previousScrollY - 20) {
            if (!_isNavBarVisible) {
              setState(() {
                _isNavBarVisible = true;
                _animationController.reverse(); // 执行显示动画
              });
            }
          }
          
          _previousScrollY = currentScrollY;
          return true;
        },
        child: Stack(
          children: [
            const _Body(),
            const ArrowOnTop(),
            // 用SlideTransition实现NavBar的滑入滑出动画
            SlideTransition(
              position: Tween<Offset>(
                begin: Offset.zero, // 初始显示位置
                end: const Offset(0, -1), // 隐藏时向上滑出屏幕
              ).animate(_animationController),
              child: Responsive.isTablet(context) || Responsive.isMobile(context)
                  ? const _NavBarTablet()
                  : const _NavbarDesktop(),
            ),
          ],
        ),
      ),
    ),
  );
}

关键说明

  • 滚动阈值:设置60px和20px的阈值是为了避免轻微滚动就触发显示/隐藏,提升交互稳定性,你可以根据自己的需求调整数值。
  • 动画自定义:如果不想用滑入滑出效果,也可以替换为AnimatedContainer修改NavBar的高度或透明度,实现不同的过渡样式。
  • 替代监听方式:如果_Body中的滚动组件(如ListView)有独立的ScrollController,也可以通过给ScrollController添加addListener来监听滚动,逻辑和上述方案一致。

内容的提问来源于stack exchange,提问作者dosytres

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 10:12:22