Flutter : Drawer (Side Menu) + Bottom Tab Bar with Fab Button Custom UI
The Bottom Navigation bar and Drawer have become popular in the last few years for navigation between different UI. Many developers use bottom navigation and Drawer because most of the app is available now using this widget for navigation between different screens.
The bottom navigation bar in Flutter can contain multiple items such as text labels, icons, or both. It allows the user to navigate between the top-level views of an app quickly. If we are using a larger screen, it is better to use a side navigation bar.
First, add the image that you will be using in the assets section of the pubspec.yaml file. for Drawer background header
assets:
- assets/bg.jpeg
Now, follow the steps to implement navigation drawer with bottom tab bar custom ui in our Flutter app:
Start
by creating a new Flutter project in either of VS Code or Android
Studio. Replace the Flutter default counter application in main.dart
with your own stateful widget.
You should have something like this:
import 'package:flutter/material.dart';
import 'package:intro_app_custom_ui/screens/welcome/welcome.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: FabTabs(selectedIndex:0),
);
}
}
Before Create Home
stateful widget create home.dart file in home folder, then inside of it with the following code:
import 'package:bottomtabbarwithsidemenu/screens/drawer/sidemenu.dart';
import 'package:flutter/material.dart';
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
@override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
@override
Widget build(BuildContext context) {
return Scaffold(
drawer: SideMenu(),
appBar: AppBar(
title: Text("Home"),
backgroundColor: Colors.pinkAccent,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'HOME',style: TextStyle(fontSize: 40),
),
],
),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
Same Create
Profile, Team and More
stateful widget file, then inside of it with the following code like home.dart
file change text nameBefore Create SideMenu
stateful widget create sidemenu.dart file in drawer folder, then inside of it with the following code:
import 'package:bottomtabbarwithsidemenu/screens/bottomTabBar/FabTabs.dart';
import 'package:flutter/material.dart';
class SideMenu extends StatefulWidget {
@override
State<SideMenu> createState() => _SideMenuState();
}
class _SideMenuState extends State<SideMenu> {
@override
Widget build(BuildContext context) {
return Drawer(
backgroundColor: Colors.white,
child: ListView(
padding: EdgeInsets.zero,
children: [
DrawerHeader(
child: Text('DevHubSpot', style: TextStyle(color: Colors.white, fontSize: 25)),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(1.0),
bottomRight: Radius.circular(1.0),
),
color: Colors.white,
image: DecorationImage(
fit: BoxFit.fill, image: AssetImage('assets/bg.jpeg')
)
),
),
ListTile(
leading: Icon(Icons.home_filled),
title: Text("Home"),
onTap: () => {
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => FabTabs(selectedIndex:0)))
},
),
ListTile(
leading: Icon(Icons.person),
title: Text("Profile"),
onTap: () => {
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => FabTabs(selectedIndex:1)))
},
),
ListTile(
leading: Icon(Icons.person_pin_outlined),
title: Text("Team"),
onTap: () => {
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => FabTabs(selectedIndex:2)))
},
),
ListTile(
leading: Icon(Icons.more_horiz_outlined),
title: Text("More"),
onTap: () => {
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => FabTabs(selectedIndex:3)))
},
)
],
),
);
}
}
Before Create FabTabs
stateful widget create FabTabs.dart file in bottomTabBar folder, then inside of it with the following code:
import 'package:bottomtabbarwithsidemenu/screens/home/home.dart';
import 'package:bottomtabbarwithsidemenu/screens/more/more.dart';
import 'package:bottomtabbarwithsidemenu/screens/profile/profile.dart';
import 'package:bottomtabbarwithsidemenu/screens/team/team.dart';
import 'package:flutter/material.dart';
class FabTabs extends StatefulWidget {
int selectedIndex = 0;
FabTabs({required this.selectedIndex});
@override
State<FabTabs> createState() => _FabTabsState();
}
class _FabTabsState extends State<FabTabs> {
int currentIndex = 0;
void onItemTapped(int index){
setState(() {
widget.selectedIndex = index;
currentIndex = widget.selectedIndex;
});
}
@override
void initState() {
onItemTapped(widget.selectedIndex);
// TODO: implement initState
super.initState();
}
final List<Widget> pages = [
Home(),
Profile(),
Team(),
More()
];
final PageStorageBucket bucket = PageStorageBucket();
@override
Widget build(BuildContext context) {
Widget currentScreen = currentIndex == 0 ? Home() : currentIndex == 1 ? Profile() :currentIndex == 2 ?Team():More();
return Scaffold(
body: PageStorage(
child: currentScreen,
bucket: bucket,
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.purple,
child: Icon(Icons.add),
onPressed: () {
print("add fab button");
},
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: BottomAppBar(
shape: CircularNotchedRectangle(),
notchMargin: 10,
child: Container(
height: 60,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
MaterialButton(
minWidth: 50,
onPressed: (){
setState(() {
currentScreen = Home();
currentIndex = 0;
});
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.home_filled,
color: currentIndex == 0 ? Colors.pinkAccent : Colors.grey,
),
Text(
"Home",
style: TextStyle(color: currentIndex == 0 ? Colors.pinkAccent : Colors.grey),
)
],
),
),
MaterialButton(
minWidth: 50,
onPressed: (){
setState(() {
currentScreen = Profile();
currentIndex = 1;
});
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.person,
color: currentIndex == 1 ? Colors.blueAccent : Colors.grey,
),
Text(
"Home",
style: TextStyle(color: currentIndex == 1 ? Colors.blueAccent : Colors.grey),
)
],
),
)
],
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
MaterialButton(
minWidth: 50,
onPressed: (){
setState(() {
currentScreen = Team();
currentIndex = 2;
});
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.person_pin_outlined,
color: currentIndex == 2 ? Colors.blue : Colors.grey,
),
Text(
"Team",
style: TextStyle(color: currentIndex == 2 ? Colors.blue : Colors.grey),
)
],
),
),
MaterialButton(
minWidth: 50,
onPressed: (){
setState(() {
currentScreen = More();
currentIndex = 3;
});
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.more_horiz_outlined,
color: currentIndex == 3 ? Colors.orangeAccent : Colors.grey,
),
Text(
"More",
style: TextStyle(color: currentIndex == 3 ? Colors.orangeAccent : Colors.grey),
)
],
),
)
],
)
],
),
),
),
);
}
}
Output: