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

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 TabsPage now 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's IndexedStack, so they always appear with the bottom bar.
  • The side drawer uses the global key to tell TabsPage which tab to select, instead of opening a new standalone Scaffold without the bottom bar.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 16:17:29