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

Flutter全局Bottom Navigation Bar配置及路由页面关联实现问询

没问题!我刚好做过类似的需求,给你一套完整的实现方案,包含代码示例和关键要点,你直接抄就能用~

核心实现思路

要实现全局底部导航栏 + 路由管理页面,核心是把底部导航栏放在一个主页面中,通过嵌套Navigator来管理各个子页面的路由,同时监听路由变化同步更新导航栏的选中状态:

  1. 先给每个底部导航项对应的页面注册命名路由
  2. 主页面承载BottomNavigationBar和嵌套的Navigator,负责路由跳转逻辑
  3. 监听路由变化,确保用户不管是点击底部导航还是通过页面内跳转切换路由,导航栏选中状态都能同步
完整可运行示例代码
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '全局底部导航示例',
      theme: ThemeData(primarySwatch: Colors.blue),
      // 注册所有底部导航对应的命名路由
      routes: {
        '/home': (context) => const HomePage(),
        '/discover': (context) => const DiscoverPage(),
        '/profile': (context) => const ProfilePage(),
      },
      home: const MainBottomNavPage(),
    );
  }
}

// 主页面:承载底部导航栏和路由容器
class MainBottomNavPage extends StatefulWidget {
  const MainBottomNavPage({super.key});

  @override
  State<MainBottomNavPage> createState() => _MainBottomNavPageState();
}

class _MainBottomNavPageState extends State<MainBottomNavPage> {
  int _selectedIndex = 0;
  // 路由名称和导航栏索引的映射,用于同步状态
  final Map<String, int> _routeIndexMap = {
    '/home': 0,
    '/discover': 1,
    '/profile': 2,
  };

  @override
  void initState() {
    super.initState();
    // 页面初始化后监听路由变化,同步导航栏选中状态
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _syncSelectedIndexWithRoute();
      Navigator.of(context).addListener(_syncSelectedIndexWithRoute);
    });
  }

  @override
  void dispose() {
    // 销毁时移除监听,避免内存泄漏
    Navigator.of(context).removeListener(_syncSelectedIndexWithRoute);
    super.dispose();
  }

  // 根据当前路由更新导航栏选中索引
  void _syncSelectedIndexWithRoute() {
    final currentRouteName = ModalRoute.of(context)?.settings.name;
    setState(() {
      _selectedIndex = _routeIndexMap[currentRouteName] ?? 0;
    });
  }

  // 底部导航栏点击事件:跳转到对应路由
  void _onNavItemTapped(int index) {
    String targetRoute;
    switch (index) {
      case 0:
        targetRoute = '/home';
        break;
      case 1:
        targetRoute = '/discover';
        break;
      case 2:
        targetRoute = '/profile';
        break;
      default:
        targetRoute = '/home';
    }
    // 避免重复跳转同一个路由
    if (ModalRoute.of(context)?.settings.name != targetRoute) {
      Navigator.pushReplacementNamed(context, targetRoute);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // 用嵌套Navigator管理子页面路由,确保底部导航始终显示
      body: const Navigator(
        initialRoute: '/home',
        onGenerateRoute: (settings) {
          return MaterialPageRoute(
            builder: (context) {
              switch (settings.name) {
                case '/home':
                  return const HomePage();
                case '/discover':
                  return const DiscoverPage();
                case '/profile':
                  return const ProfilePage();
                default:
                  return const HomePage();
              }
            },
          );
        },
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home_filled),
            label: '首页',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.explore),
            label: '发现',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: '我的',
          ),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.blueAccent,
        unselectedItemColor: Colors.grey,
        onTap: _onNavItemTapped,
      ),
    );
  }
}

// 示例页面:首页
class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('首页')),
      body: Center(
        child: ElevatedButton(
          child: const Text('跳转到我的页面'),
          onPressed: () => Navigator.pushNamed(context, '/profile'),
        ),
      ),
    );
  }
}

// 示例页面:发现页
class DiscoverPage extends StatelessWidget {
  const DiscoverPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('发现')),
      body: const Center(child: Text('发现页内容')),
    );
  }
}

// 示例页面:我的页面
class ProfilePage extends StatelessWidget {
  const ProfilePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('我的')),
      body: const Center(child: Text('我的页面内容')),
    );
  }
}
关键细节说明
  • 路由同步:通过Navigator的监听器,不管用户是点击底部导航还是页面内按钮跳转,底部导航的选中状态都会自动更新
  • 路由栈优化:使用pushReplacementNamed跳转,避免路由栈堆积,保证每次切换后路由栈只有当前页面
  • 嵌套Navigator:主页面的body使用嵌套Navigator,这样每个子页面可以拥有自己的AppBar,同时底部导航栏始终固定在页面底部

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 01:47:33