A common navigation pattern is to have clickable items at the bottom of the screen. This pattern is commonly used in both iOS and Android so this tutorial is important if you are targetting either or both platforms. The component or widget used to achieve that is the BottomNavigationBar.

In this tutorial we will look at the BottomNavigationBar widget and how to use it. Let's start.

Example 1: BottomNavigationBar and PageView

Let us look at a simple bottomnavigation example in flutter using BottomNavigationBar and PageView classes.

Here is the demo screenshot of this example:

Flutter Tutorial-Flutter Bottom Navigation Bar

Flutter Tutorial-Flutter Bottom Nav...
Flutter Tutorial-Flutter Bottom Navigation Bar

Flutter BottomNavigationBar

This example will comprise the following files:

  • BottomNavigation.dart

Step 1: Create Project.

  1. Open your favorite Flutter IDE.
  2. Go to File-->New-->Project to create a new project.

Step 2: Dependencies.

No external dependencies are needed for this project.

Step 4: Write Dart Code

Write your code as follows:

*(a). BottomNavigation.dart

Create a file Dart named BottomNavigation.dart

Here is the full code

import 'package:flutter/material.dart';

class BottomNavigation extends StatefulWidget {
  const BottomNavigation({Key? key, required this.title}) : super(key: key);
  final String title;

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

class _BottomNavigationState extends State<BottomNavigation> {
  PageController? _pageController;
  var _page = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: PageView(
        controller: _pageController,
        physics: const BouncingScrollPhysics(),
        onPageChanged: onPageChanged,
        children: <Widget>[
          Container(
            color: Colors.orangeAccent,
          ),
          Container(
            color: Colors.redAccent,
          ),
          Container(
            color: Colors.blueAccent,
          ),
        ],
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: const [
          BottomNavigationBarItem(
            icon: Icon(Icons.photo),
            label: "Photo",
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.map),
            label: "Map",
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.favorite),
            label: "Favorite",
          ),
        ],
        onTap: navigationTapped,
        currentIndex: _page,
      ),
    );
  }

  ///
  /// Bottom Navigation tap listener
  ///
  void navigationTapped(int page) {
    _pageController!.animateToPage(
      page,
      duration: const Duration(milliseconds: 300),
      curve: Curves.easeIn,
    );
  }

  void onPageChanged(int page) {
    setState(() {
      _page = page;
    });
  }

  @override
  void initState() {
    super.initState();
    _pageController = PageController();
  }

  @override
  void dispose() {
    super.dispose();
    _pageController!.dispose();
  }
}

Run

Simply copy the source code into your Flutter Project, Build and Run.

Reference.

Download code here.
Follow code author here.

Example 2: BottomNavigationBar - Tabs with GridViews

In this example we look at how to switch through BottomNavigation Items with pages showing GridView. Each page will have a gridview with different data set. This can easily used as a template in creating apps that list items.

Here's the demo.


Step 1: Dependencies

No special dependency is needed for this project.

Step 2: Create Homepage with BottomNavigationBar

Start by creating the main.dart file. Import the material package:

import 'package:flutter/material.dart';

Create Homepage as a stateful widget:

class Homepage extends StatefulWidget {
  @override
  createState() => HomepageState();
}

Extend the State to create the homepage state. In this class we will hold an integer instance field known as index. This will represent the selected page:

class HomepageState extends State<Homepage> {
  int index = 0;

Now build and return a Scaffold widget containing the appbar, body and bottomnavigationbar:

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: new AppBar(
        title: new Text('BottomNav Grids'),
      ),
      body: HomeBody(),
      bottomNavigationBar: MyBottomNavBar(
        index: index,
        callback: (newIndex) => setState(
              () => this.index = newIndex,
            ),
      ),
    );
  }
}

Step 3: Create a GidView with Data

Each page in our app will contain a gridview with data. So we need a stateless widget to ceate a representation of a page for us:

class HomeBody extends StatelessWidget {

Now create a function that returns us a gridview with our data:

 //Create and Return GridView filled with our data
  Widget createGridView(BuildContext context) {
    var spacecrafts = ["James Web","Enterprise","Hubble","Kepler","Juno","Casini","Columbia","Challenger","Mariner","Pioneer","Huygens","Galileo","Dawn","Star Dust","Apollo","Spitzer","WMAP","Swift","Atlantis"];
    spacecrafts.shuffle();
    return new GridView.builder(
      itemCount: spacecrafts.length,
      gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
      itemBuilder: (BuildContext context, int index) {
        return new GestureDetector(
          child: new Card(
            elevation: 5.0,
            child: new Container(
              alignment: Alignment.centerLeft,
              margin: new EdgeInsets.only(top: 10.0, bottom: 10.0,left: 10.0),
              child: new Text(spacecrafts[index]),
            ),
          ),
    );
    }
    );
  }

Now build the widget to represent the page with the gridview at the center:

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Center(
        child: createGridView(context),
      ),
    );
  }
}

Step 4: Create BottomNavigationBar

The bottomnavigationbar is itself a widget like all other widgets. Thus we need to create it programmatically. We will do this by extending the StatelessWidget and overriding the build() method.

class MyBottomNavBar extends StatelessWidget {

Two instance fields will be defined. They will hold arguments that we will be receiving via the constructor:

  MyBottomNavBar({this.index, this.callback});

  final int index;
  final Function(int) callback;

Here is how you build and return a bottomnavigationbar with three items containing text and icons:

  @override
  Widget build(BuildContext context) {
    /// BottomNavigationBar is automatically set to type 'fixed'
    /// when there are three of less items
    return BottomNavigationBar(
      currentIndex: index,
      onTap: callback,
      items: <BottomNavigationBarItem>[
        BottomNavigationBarItem(
          icon: Icon(Icons.home),
          title: Text('Plasma'),
        ),
         BottomNavigationBarItem(
          icon: Icon(Icons.usb),
          title: Text('Laser'),
        ),
        BottomNavigationBarItem(
          icon: Icon(Icons.threed_rotation),
          title: Text('Warp'),
        ),
      ],
    );
  }
}

Full Code

Here is the full code:

main.dart

import 'package:flutter/material.dart';

class Homepage extends StatefulWidget {
  @override
  createState() => HomepageState();
}

class HomepageState extends State<Homepage> {
  int index = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: new AppBar(
        title: new Text('BottomNav Grids'),
      ),
      body: HomeBody(),
      bottomNavigationBar: MyBottomNavBar(
        index: index,
        callback: (newIndex) => setState(
              () => this.index = newIndex,
            ),
      ),
    );
  }
}

//This represents the Body. We show GridView in Body
class HomeBody extends StatelessWidget {

  //Create and Return GridView filled with our data
  Widget createGridView(BuildContext context) {
    var spacecrafts = ["James Web","Enterprise","Hubble","Kepler","Juno","Casini","Columbia","Challenger","Mariner","Pioneer","Huygens","Galileo","Dawn","Star Dust","Apollo","Spitzer","WMAP","Swift","Atlantis"];
    spacecrafts.shuffle();
    return new GridView.builder(
      itemCount: spacecrafts.length,
      gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
      itemBuilder: (BuildContext context, int index) {
        return new GestureDetector(
          child: new Card(
            elevation: 5.0,
            child: new Container(
              alignment: Alignment.centerLeft,
              margin: new EdgeInsets.only(top: 10.0, bottom: 10.0,left: 10.0),
              child: new Text(spacecrafts[index]),
            ),
          ),
    );
    }
    );
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Center(
        child: createGridView(context),
      ),
    );
  }
}

class MyBottomNavBar extends StatelessWidget {
  MyBottomNavBar({this.index, this.callback});

  final int index;
  final Function(int) callback;

  @override
  Widget build(BuildContext context) {
    /// BottomNavigationBar is automatically set to type 'fixed'
    /// when there are three of less items
    return BottomNavigationBar(
      currentIndex: index,
      onTap: callback,
      items: <BottomNavigationBarItem>[
        BottomNavigationBarItem(
          icon: Icon(Icons.home),
          title: Text('Plasma'),
        ),
         BottomNavigationBarItem(
          icon: Icon(Icons.usb),
          title: Text('Laser'),
        ),
        BottomNavigationBarItem(
          icon: Icon(Icons.threed_rotation),
          title: Text('Warp'),
        ),
      ],
    );
  }
}

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

void main() => runApp(MyApp());
Download

Here are reference resources:

Number Location Link
1. GitHub Direct Download
2. GitHub Browse
3. YouTube Video Tutorial
4. YouTube ProgrammingWizards TV Channel