Prabhashi Buddhima
Prabhashi Buddhima

Reputation: 1315

Flutter drawer with bottom navigator tabs

I'm still a beginner at flutter and I want to create a flutter mobile app with a side drawer and a bottom navigation tab bar. I have created my app with a side drawer and a bottom navigation, but my problem is I want to open the Home page from both drawer and bottom navigation tab.

Now the drawer is opening the home page but it's not showing the bottom navigator.

here's my code

main.dart

import 'package:discover_me/screens/home.dart';
import 'package:discover_me/screens/search.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,
      routes: {
        // '/': (context) => Home(),
        '/home': (context) => Home(),
        '/search': (context) => SearchPage(),
      },
    );
  }
}

tabspage.dart

import 'package:discover_me/shared/bottom_tabs.dart';
import 'package:flutter/material.dart';

class TabsPage extends StatefulWidget {
  @override
  _TabsPageState createState() => _TabsPageState();
}

class _TabsPageState extends State<TabsPage> {
  int _selectedIndex = 0;
  static const TextStyle optionStyle =
      TextStyle(fontSize: 30, fontWeight: FontWeight.bold);


  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Scaffold(
        body: IndexedStack(
        index: _selectedIndex,
        children: [
          for (final tabItem in TabNavigationItem.items) tabItem.page,
        ],
      ),
      // drawer: SideMenu(),
      ),
      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,
      ),
    );
  }
}

bottom_tabs.dart

import 'package:discover_me/screens/home.dart';
import 'package:discover_me/screens/search.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';

class TabNavigationItem {
  final Widget page;
  final Widget title;
  final Icon icon;

  TabNavigationItem({this.page, this.title, this.icon});

static List<TabNavigationItem> get items => [
        TabNavigationItem(
          page: Home(),
          icon: Icon(Icons.home),
          title: Text("Home"),
        ),
        TabNavigationItem(
          page: SearchPage(),
          icon: Icon(Icons.home),
          title: Text("Home"),
        ),
        TabNavigationItem(
          page: Home(),
          icon: Icon(Icons.home),
          title: Text("Home"),
        ),
      ];


}

home.dart

import 'package:discover_me/jsn_objects/visit_places.dart';
import 'package:discover_me/tabs/tabspage.dart';
import 'package:discover_me/widgets/side_menu.dart';
import 'package:flutter/material.dart';
import 'dart:convert';

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  bool expanded = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      
      drawer: SideMenu(),
      appBar: 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: () {
                Navigator.pushNamed(
                  context, '/search'
                );
              }),
        ],
      ),
      body: 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;
                }),
              ),
            ],
          ),

        ],
        
      ),
     
    );
  }
}

I want to call Home Page with the bottom navigation from the drawer. Could you please help me with this?

Upvotes: 3

Views: 4645

Answers (2)

Prabhashi Buddhima
Prabhashi Buddhima

Reputation: 1315

Finally, I have managed to solve my issue.

I have add a constructor parameter to TabsPage and pass the value when the page called from the side drawer.

here's the solution

main.dart

import 'package:flutter/material.dart';
import 'package:tabsdrawer/tabs/tabspage.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
          scaffoldBackgroundColor: Colors.white, primaryColor: Colors.white),
      home: TabsPage(selectedIndex: 0),
      debugShowCheckedModeBanner: false,
    );
  }
}

sidemenu.dart file

import 'package:flutter/material.dart';
import 'package:tabsdrawer/tabs/tabspage.dart';

class SideMenu extends StatefulWidget {
  @override
  _SideMenuState createState() => _SideMenuState();
}

class _SideMenuState extends State<SideMenu> {
  @override
  Widget build(BuildContext context) {
    return Drawer(
      child: ListView(
        padding: EdgeInsets.zero,
        children: [
          DrawerHeader(
            child: Text(
              'Discover Sri Lanka',
              style: TextStyle(color: Colors.white, fontSize: 25),
            ),
            decoration: BoxDecoration(
                borderRadius: BorderRadius.only(
                    bottomLeft: Radius.circular(10.0),
                    bottomRight: Radius.circular(10.0)),
                color: Colors.white,
                image: DecorationImage(
                    fit: BoxFit.fill, image: AssetImage('assets/sideimg.jpg'))),
          ),
          ListTile(
          
            leading: Icon(Icons.home),
            title: Text('Home'),
            onTap: () => {
              Navigator.pushReplacement(
                  context,
                  MaterialPageRoute(builder: (context) => TabsPage(selectedIndex: 0)),
                )
            },
          ),
          ListTile(
            leading: Icon(Icons.search),
            title: Text('Search'),
            onTap: () => {
              Navigator.pushReplacement(
                  context,
                  MaterialPageRoute(builder: (context) => TabsPage(selectedIndex: 1)),
                ),
            },
          ),
          ListTile(
            leading: Icon(Icons.settings),
            title: Text('Profile'),
            onTap: () => {
              Navigator.pushReplacement(
                  context,
                  MaterialPageRoute(builder: (context) => TabsPage(selectedIndex: 2)),
                ),
            },
          ),
          
        ],
      ),
    );
  }
}

tabspage.dart

import 'package:flutter/material.dart';
import 'package:tabsdrawer/tabs/bottom_tabs.dart';

class TabsPage extends StatefulWidget {
  int selectedIndex = 0;

  TabsPage({this.selectedIndex});

  @override
  _TabsPageState createState() => _TabsPageState();
}

class _TabsPageState extends State<TabsPage> {
  int _selectedIndex = 0;
  
  void _onItemTapped(int index) {
    setState(() {
      widget.selectedIndex = index;
      _selectedIndex = widget.selectedIndex;
      print(_selectedIndex);
    });
  }
  @override
  void initState() {
    _onItemTapped(widget.selectedIndex);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Scaffold(
        body: IndexedStack(
          index: widget.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.search),
            title: Text('Search'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.verified_user),
            title: Text('Profile'),
          ),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.amber[800],
        onTap: _onItemTapped,
      ),
    );
  }
}

bottom_tabs.dart

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:tabsdrawer/screens/home.dart';
import 'package:tabsdrawer/screens/profile.dart';
import 'package:tabsdrawer/screens/search.dart';

class TabNavigationItem {
  final Widget page;
  final Widget title;
  final Icon icon;

  TabNavigationItem({this.page, this.title, this.icon});

  static List<TabNavigationItem> get items => [
        TabNavigationItem(
          page: Home(),
          icon: Icon(Icons.home),
          title: Text("Home"),
        ),
        TabNavigationItem(
          page: Search(),
          icon: Icon(Icons.search),
          title: Text("Search"),
        ),
        TabNavigationItem(
          page: Profile(),
          icon: Icon(Icons.home),
          title: Text("Home"),
        ),
      ];
}

home.dart

import 'package:flutter/material.dart';
import 'package:tabsdrawer/sidemenu/side_menu.dart';

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      drawer: SideMenu(),
      appBar: 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: () {
                Navigator.pushNamed(context, '/search');
              }),
        ],
      ),
      body: Center(
        child: Text('Home Page'),
      ),
    );
  }
}

I have wrote an article mentioning the whole solution in here, https://medium.com/@prabhashibuddhima/flutter-how-to-make-flutter-side-drawer-side-menu-work-with-bottom-navigation-bar-bottom-tab-ce66a95e25fe

Upvotes: 3

It's not showing BottomNavigationBar because you didn't call it in your HomePage. You can create a generic BottomNavigationBar and call it wherever you want to see it and you can control the selected tab with setting it to provider if you want.

So basically your Home page should be like this :

import 'package:discover_me/jsn_objects/visit_places.dart';
import 'package:discover_me/tabs/tabspage.dart';
import 'package:discover_me/widgets/side_menu.dart';
import 'package:flutter/material.dart';
import 'dart:convert';

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  bool expanded = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      drawer: SideMenu(),
      appBar: 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: () {
                Navigator.pushNamed(context, '/search');
              }),
        ],
      ),
      body: 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;
                }),
              ),
            ],
          ),
        ],
      ),
      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,
      ),
    );
  }
}

But it's not good to create new BottomNavigationBar for your every page. I suggest you to create a generic one

Upvotes: 4

Related Questions