Bottom Navigation Bars in Flutter
Bottom Navigation Bars are a popular UI component in mobile applications, providing quick access to various app sections. They allow users to navigate between major screens efficiently and are often seen in apps like YouTube, Instagram, and Gmail. In this guide, we’ll explore how to implement and customize Bottom Navigation Bars in Flutter, step by step.
What is a Bottom Navigation Bar?
A Bottom Navigation Bar is a widget placed at the bottom of an app's screen. It typically contains multiple items, each representing a different section of the app. When a user taps on an item, the app navigates to the corresponding section.
Why Use Bottom Navigation Bars?
- Quick Navigation: Provides easy access to primary app sections.
- Compact Design: Maximizes screen space while maintaining usability.
- Intuitive User Experience: Familiar UI pattern for most users.
- Customizable: You can style and configure it to match your app's theme.
Steps to Implement a Bottom Navigation Bar
1. Basic BottomNavigationBar
The BottomNavigationBar
widget is the primary tool for creating a bottom navigation bar in Flutter.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
int _selectedIndex = 0;
// List of screens corresponding to each navigation item
static const List<Widget> _pages = <Widget>[
Center(child: Text('Home Screen')),
Center(child: Text('Search Screen')),
Center(child: Text('Profile Screen')),
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Bottom Navigation Example'),
),
body: _pages[_selectedIndex],
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
label: 'Search',
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: 'Profile',
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.blue,
onTap: _onItemTapped,
),
);
}
}
Understanding the Key Components
items
: A list ofBottomNavigationBarItem
objects, each defining an icon and a label. Example:BottomNavigationBarItem( icon: Icon(Icons.home), label: 'Home', )
currentIndex
: The index of the currently selected item.onTap
: A callback function triggered when an item is tapped. It is used to update thecurrentIndex
.selectedItemColor
: Defines the color of the selected item.
2. Customizing the Bottom Navigation Bar
You can style and configure the Bottom Navigation Bar to match your app’s design.
bottomNavigationBar: BottomNavigationBar(
backgroundColor: Colors.grey[900], // Change the background color
selectedItemColor: Colors.yellow, // Selected item color
unselectedItemColor: Colors.white, // Unselected item color
selectedFontSize: 16.0, // Font size of the selected label
unselectedFontSize: 14.0, // Font size of unselected labels
type: BottomNavigationBarType.fixed, // Ensures labels are always visible
items: [
BottomNavigationBarItem(
icon: Icon(Icons.dashboard),
label: 'Dashboard',
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: 'Settings',
),
BottomNavigationBarItem(
icon: Icon(Icons.notifications),
label: 'Notifications',
),
],
)
3. Handling Dynamic Navigation with Screens
You can dynamically navigate to new screens using a Navigator
or IndexedStack
.
Example Using Navigator:
void _onItemTapped(int index) {
if (index == 0) {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => HomeScreen()),
);
} else if (index == 1) {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SearchScreen()),
);
}
}
Example Using IndexedStack:
body: IndexedStack(
index: _selectedIndex,
children: [
HomeScreen(),
SearchScreen(),
ProfileScreen(),
],
),
4. Floating Bottom Navigation Bars
For a modern look, you can use a floating Bottom Navigation Bar. This can be achieved with a Container
or third-party packages like salomon_bottom_bar
.
bottomNavigationBar: Container(
margin: EdgeInsets.all(16.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(30),
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 10,
spreadRadius: 5,
),
],
),
child: BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
label: 'Search',
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: 'Profile',
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.blue,
onTap: _onItemTapped,
),
)
Common Errors and Solutions
- Navigation Index Not Updating: Ensure the
_onItemTapped
function is updating thecurrentIndex
and callingsetState
. - UI Overlaps with BottomNavigationBar: Wrap the content in
SafeArea
to avoid overlap with system UI. - Too Many Items: BottomNavigationBar supports a maximum of five items. For more, consider using a
Drawer
.
Best Practices
- Limit Items: Use no more than 3-5 items to avoid clutter.
- Label Importance: Use clear and concise labels.
- Consistent Design: Match the navigation bar design with the app’s theme.
- Highlight Active Item: Always indicate which item is currently selected.
Complete Example
Here’s a complete example demonstrating a fully customized Bottom Navigation Bar with dynamic screens.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: NavigationExample(),
);
}
}
class NavigationExample extends StatefulWidget {
@override
_NavigationExampleState createState() => _NavigationExampleState();
}
class _NavigationExampleState extends State<NavigationExample> {
int _selectedIndex = 0;
static const List<Widget> _pages = <Widget>[
Center(child: Text('Home Screen')),
Center(child: Text('Search Screen')),
Center(child: Text('Profile Screen')),
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Bottom Navigation Bar Example'),
),
body: _pages[_selectedIndex],
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
label: 'Search',
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: 'Profile',
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.blue,
onTap: _onItemTapped,
),
);
}
}
Conclusion
Bottom Navigation Bars are a great way to enhance user navigation in Flutter apps. By customizing their design and behavior, you can create a smooth and intuitive user experience. Practice building your own Bottom Navigation Bars to get comfortable with their implementation and styling!