Using the BottomNavigationBar Widget for Implementing Bottom Navigation Menus in Flutter

Flutter offers a rich set of widgets to facilitate building beautiful and functional user interfaces for cross-platform applications. One essential widget for creating intuitive navigation is the BottomNavigationBar. This guide delves into effectively utilizing the BottomNavigationBar widget to implement bottom navigation menus in your Flutter apps.

What is the BottomNavigationBar Widget?

The BottomNavigationBar is a Flutter widget that displays a bar at the bottom of the screen for selecting between a small number of views, typically between three and five. It’s a convenient and user-friendly way to allow users to switch between different sections or features within an app.

Why Use BottomNavigationBar?

  • Improved User Experience: Provides a straightforward and intuitive navigation method.
  • Easy Access: Allows users to quickly access primary app features from any screen.
  • Consistent Design: Helps maintain a uniform design across your application.

How to Implement BottomNavigationBar in Flutter

To implement a bottom navigation bar, follow these steps:

Step 1: Setting up a Basic Flutter App

First, ensure you have a basic Flutter app structure. If not, create a new Flutter project using the following command:

flutter create bottom_navigation_example
cd bottom_navigation_example

Step 2: Add BottomNavigationBar to Your Scaffold

Wrap your content in a Scaffold widget, which provides the basic visual structure for your app. Within the Scaffold, use the bottomNavigationBar property to add a BottomNavigationBar.


import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Bottom Navigation Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State {
  int _currentIndex = 0; // To keep track of the current index

  final List _children = [
    HomeScreen(),
    SearchScreen(),
    ProfileScreen(),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Bottom Navigation Example'),
      ),
      body: _children[_currentIndex], // Display the current screen
      bottomNavigationBar: BottomNavigationBar(
        onTap: onTabTapped, // Function to call when tab is tapped
        currentIndex: _currentIndex, // Index of current tab
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.search),
            label: 'Search',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: 'Profile',
          ),
        ],
      ),
    );
  }

  void onTabTapped(int index) {
    setState(() {
      _currentIndex = index;
    });
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(child: Text('Home Screen'));
  }
}

class SearchScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(child: Text('Search Screen'));
  }
}

class ProfileScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(child: Text('Profile Screen'));
  }
}

In this code:

  • _currentIndex is an integer that keeps track of the currently selected tab.
  • _children is a list of widgets that represent the screens associated with each tab.
  • onTabTapped is a function that updates _currentIndex when a tab is tapped.
  • BottomNavigationBarItem creates individual tabs with icons and labels.

Step 3: Styling the BottomNavigationBar

The BottomNavigationBar widget offers various properties for customization, such as:

  • backgroundColor: Sets the background color of the navigation bar.
  • selectedItemColor: Sets the color of the selected item.
  • unselectedItemColor: Sets the color of unselected items.
  • selectedFontSize: Sets the font size of the selected label.
  • unselectedFontSize: Sets the font size of unselected labels.
  • type: Determines the layout of the navigation bar (e.g., fixed or shifting).

Here’s an example of how to style the BottomNavigationBar:


bottomNavigationBar: BottomNavigationBar(
  onTap: onTabTapped,
  currentIndex: _currentIndex,
  backgroundColor: Colors.grey[200],
  selectedItemColor: Colors.blue,
  unselectedItemColor: Colors.grey,
  selectedFontSize: 14,
  unselectedFontSize: 12,
  type: BottomNavigationBarType.fixed, // Fixed or shifting
  items: [
    BottomNavigationBarItem(
      icon: Icon(Icons.home),
      label: 'Home',
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.search),
      label: 'Search',
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.person),
      label: 'Profile',
    ),
  ],
),

Step 4: Using BottomNavigationBarType

The BottomNavigationBarType enum offers two types:

  • fixed: All labels are always visible.
  • shifting: The selected item grows in size and the background color shifts.

For the shifting type, you must provide a backgroundColor for each BottomNavigationBarItem.


bottomNavigationBar: BottomNavigationBar(
  onTap: onTabTapped,
  currentIndex: _currentIndex,
  type: BottomNavigationBarType.shifting, // Shifting type
  items: [
    BottomNavigationBarItem(
      icon: Icon(Icons.home),
      label: 'Home',
      backgroundColor: Colors.blue,
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.search),
      label: 'Search',
      backgroundColor: Colors.green,
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.person),
      label: 'Profile',
      backgroundColor: Colors.orange,
    ),
  ],
),

Complete Example

Here’s a complete example with styling and the shifting type:


import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Bottom Navigation Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State {
  int _currentIndex = 0; // To keep track of the current index

  final List _children = [
    HomeScreen(),
    SearchScreen(),
    ProfileScreen(),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Bottom Navigation Example'),
      ),
      body: _children[_currentIndex], // Display the current screen
      bottomNavigationBar: BottomNavigationBar(
        onTap: onTabTapped, // Function to call when tab is tapped
        currentIndex: _currentIndex, // Index of current tab
        type: BottomNavigationBarType.shifting,
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'Home',
            backgroundColor: Colors.blue,
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.search),
            label: 'Search',
            backgroundColor: Colors.green,
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: 'Profile',
            backgroundColor: Colors.orange,
          ),
        ],
      ),
    );
  }

  void onTabTapped(int index) {
    setState(() {
      _currentIndex = index;
    });
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(child: Text('Home Screen'));
  }
}

class SearchScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(child: Text('Search Screen'));
  }
}

class ProfileScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(child: Text('Profile Screen'));
  }
}

Conclusion

The BottomNavigationBar widget is an invaluable tool for implementing bottom navigation menus in Flutter, making it easier to provide a seamless and intuitive user experience. With straightforward implementation and extensive customization options, you can efficiently enhance your Flutter apps with organized and easily accessible navigation.