Flutter初学者求助:实现侧边栏与底部导航栏打开带底部栏的首页
Hey there! Let's fix that issue where your Home page doesn't show the bottom navigation bar when opened from the side drawer. The core problem here is that right now, you're navigating directly to the Home widget (which is its own full Scaffold) instead of switching to the Home tab within your existing TabsPage (the one that includes the bottom navigation bar).
Here's a step-by-step solution with code modifications:
1. Restructure your main layout to keep the drawer and bottom nav global
Move the side drawer to your TabsPage (the parent widget with the bottom navigation bar) so it's a global drawer for the entire app. This way, all pages shown via the bottom nav or drawer will live inside the TabsPage and retain the bottom bar.
Update tabspage.dart:
import 'package:discover_me/shared/bottom_tabs.dart'; import 'package:discover_me/widgets/side_menu.dart'; import 'package:flutter/material.dart'; class TabsPage extends StatefulWidget { // Add a global key to let the drawer control tab selection static final GlobalKey<_TabsPageState> tabKey = GlobalKey<_TabsPageState>(); @override _TabsPageState createState() => _TabsPageState(); } class _TabsPageState extends State<TabsPage> { int _selectedIndex = 0; // Method to update the selected tab from outside this widget void setSelectedIndex(int index) { setState(() { _selectedIndex = index; }); } void _onItemTapped(int index) { setState(() { _selectedIndex = index; }); } // Generate app bar based on the current selected tab AppBar _getCurrentAppBar() { switch (_selectedIndex) { case 0: return AppBar( leading: Builder( builder: (BuildContext context) { return RotatedBox( quarterTurns: 1, child: IconButton( icon: Icon(Icons.bar_chart_rounded, color: Colors.black), onPressed: () => Scaffold.of(context).openDrawer(), ), ); }, ), backgroundColor: Colors.white, elevation: 0.0, actions: [ IconButton( color: Colors.black, icon: Icon(Icons.search), onPressed: () => setSelectedIndex(1), // Switch to search tab directly ), ], ); case 1: return AppBar( title: Text('Search'), backgroundColor: Colors.white, elevation: 0.0, ); case 2: return AppBar( title: Text('Third Page'), backgroundColor: Colors.white, elevation: 0.0, ); default: return AppBar(); } } @override Widget build(BuildContext context) { return Scaffold( appBar: _getCurrentAppBar(), drawer: SideMenu(), // Move the drawer here (global for the app) body: IndexedStack( index: _selectedIndex, children: [ for (final tabItem in TabNavigationItem.items) tabItem.page, ], ), bottomNavigationBar: BottomNavigationBar( items: const <BottomNavigationBarItem>[ BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('Home')), BottomNavigationBarItem(icon: Icon(Icons.business), title: Text('Business')), BottomNavigationBarItem(icon: Icon(Icons.school), title: Text('School')), ], currentIndex: _selectedIndex, selectedItemColor: Colors.amber[800], onTap: _onItemTapped, ), ); } }
2. Simplify your Home widget (remove its Scaffold)
Since TabsPage now handles the app bar and drawer, your Home widget only needs to contain its body content:
Update home.dart:
import 'package:flutter/material.dart'; class Home extends StatefulWidget { @override _HomeState createState() => _HomeState(); } class _HomeState extends State<Home> { bool expanded = false; @override Widget build(BuildContext context) { // Remove the Scaffold here - let TabsPage handle the parent layout return Column( children: [ Container(color: Colors.green, height: 100), AnimatedContainer( duration: const Duration(milliseconds: 200), height: expanded ? 120 : 0, child: Container(height: 120, color: Colors.red), ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ FloatingActionButton( heroTag: null, child: Icon(expanded ? Icons.arrow_upward : Icons.arrow_downward), onPressed: () => setState(() => expanded = !expanded), ), ], ), ], ); } }
3. Update the side drawer to switch tabs instead of navigating to routes
Modify your SideMenu to use the global key we added to TabsPage to switch tabs directly, instead of pushing new routes:
Update side_menu.dart:
import 'package:discover_me/tabs/tabspage.dart'; import 'package:flutter/material.dart'; class SideMenu extends StatelessWidget { @override Widget build(BuildContext context) { return Drawer( child: ListView( padding: EdgeInsets.zero, children: [ DrawerHeader( child: Text('Discover Me Menu'), decoration: BoxDecoration(color: Colors.blue), ), ListTile( title: Text('Home'), onTap: () { Navigator.pop(context); // Close the drawer first // Switch to the Home tab (index 0) TabsPage.tabKey.currentState?.setSelectedIndex(0); }, ), ListTile( title: Text('Search'), onTap: () { Navigator.pop(context); TabsPage.tabKey.currentState?.setSelectedIndex(1); }, ), // Add other menu items here with their respective tab indices ], ), ); } }
4. Clean up your main.dart routes
Since we're no longer using named routes to switch pages, you can remove the routes block from main.dart:
Update main.dart:
import 'package:discover_me/tabs/tabspage.dart'; import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData( scaffoldBackgroundColor: Colors.white, primaryColor: Colors.white ), home: TabsPage(), debugShowCheckedModeBanner: false, ); } }
Why this works:
- The
TabsPagenow acts as the single parent layout for your app, containing the global drawer and bottom navigation bar. - All your pages (Home, Search, etc.) are now child widgets inside
TabsPage'sIndexedStack, so they always appear with the bottom bar. - The side drawer uses the global key to tell
TabsPagewhich tab to select, instead of opening a new standaloneScaffoldwithout the bottom bar.
内容的提问来源于stack exchange,提问作者Prabhashi Buddhima

