Flutter Bottom Navigation

Create bottom navigation bars for easy screen switching

📍 What is Bottom Navigation?

Bottom Navigation Bar is a material design component that displays navigation tabs at the bottom of the screen. It allows users to quickly switch between top-level views with a single tap, making it perfect for apps with three to five primary destinations.


// Add bottom navigation to Scaffold
bottomNavigationBar: BottomNavigationBar(
  items: [...],
)
                                    

Key Bottom Navigation Concepts

📱

BottomNavigationBar

The main navigation widget

bottomNavigationBar:
  BottomNavigationBar(...)
🔘

Items

Navigation tab items

items: [
  BottomNavigationBarItem(...)
]
🎯

Current Index

Track selected tab

currentIndex: _selectedIndex
👆

OnTap

Handle tab selection

onTap: (index) {
  setState(() {...});
}

🔹 Basic Bottom Navigation

Create a simple bottom navigation bar with three tabs:

import 'package:flutter/material.dart';

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

class _MyHomePageState extends State {
  int _selectedIndex = 0;

  // List of widgets to display
  static const List _pages = [
    Center(child: Text('Home Page', style: TextStyle(fontSize: 30))),
    Center(child: Text('Search Page', style: TextStyle(fontSize: 30))),
    Center(child: Text('Profile Page', style: TextStyle(fontSize: 30))),
  ];

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Bottom Navigation Demo'),
      ),
      body: _pages[_selectedIndex],
      bottomNavigationBar: BottomNavigationBar(
        items: const [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.search),
            label: 'Search',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: 'Profile',
          ),
        ],
        currentIndex: _selectedIndex,
        onTap: _onItemTapped,
      ),
    );
  }
}

Result:

✅ Three tabs at bottom: Home, Search, Profile

✅ Tapping a tab switches the displayed page

✅ Selected tab is highlighted

🔹 Styled Bottom Navigation

Customize colors and appearance:

bottomNavigationBar: BottomNavigationBar(
  items: const [
    BottomNavigationBarItem(
      icon: Icon(Icons.home),
      label: 'Home',
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.business),
      label: 'Business',
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.school),
      label: 'School',
    ),
  ],
  currentIndex: _selectedIndex,
  selectedItemColor: Colors.blue,
  unselectedItemColor: Colors.grey,
  backgroundColor: Colors.white,
  type: BottomNavigationBarType.fixed,
  onTap: _onItemTapped,
)

Styling Properties:

  • selectedItemColor: Color of selected tab
  • unselectedItemColor: Color of unselected tabs
  • backgroundColor: Background color of the bar
  • type: fixed (all items visible) or shifting (animated)

🔹 Bottom Navigation with Pages

Create separate page widgets for each tab:

// Home Page Widget
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.home, size: 100, color: Colors.blue),
          SizedBox(height: 20),
          Text('Home Page', style: TextStyle(fontSize: 24)),
        ],
      ),
    );
  }
}

// Favorites Page Widget
class FavoritesPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.favorite, size: 100, color: Colors.red),
          SizedBox(height: 20),
          Text('Favorites Page', style: TextStyle(fontSize: 24)),
        ],
      ),
    );
  }
}

// Settings Page Widget
class SettingsPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.settings, size: 100, color: Colors.grey),
          SizedBox(height: 20),
          Text('Settings Page', style: TextStyle(fontSize: 24)),
        ],
      ),
    );
  }
}

// Main Widget
class _MyHomePageState extends State {
  int _selectedIndex = 0;

  final List _pages = [
    HomePage(),
    FavoritesPage(),
    SettingsPage(),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _pages[_selectedIndex],
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _selectedIndex,
        onTap: (index) => setState(() => _selectedIndex = index),
        items: [
          BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
          BottomNavigationBarItem(icon: Icon(Icons.favorite), label: 'Favorites'),
          BottomNavigationBarItem(icon: Icon(Icons.settings), label: 'Settings'),
        ],
      ),
    );
  }
}

🔹 Bottom Navigation with Badges

Add notification badges to navigation items:

bottomNavigationBar: BottomNavigationBar(
  items: [
    BottomNavigationBarItem(
      icon: Icon(Icons.home),
      label: 'Home',
    ),
    BottomNavigationBarItem(
      icon: Badge(
        label: Text('3'),
        child: Icon(Icons.notifications),
      ),
      label: 'Notifications',
    ),
    BottomNavigationBarItem(
      icon: Badge(
        label: Text('5'),
        backgroundColor: Colors.red,
        child: Icon(Icons.message),
      ),
      label: 'Messages',
    ),
  ],
  currentIndex: _selectedIndex,
  onTap: _onItemTapped,
)

Result:

✅ Red badge with number appears on icons

✅ Perfect for showing unread counts

🔹 Shifting Bottom Navigation

Create an animated shifting navigation bar:

bottomNavigationBar: BottomNavigationBar(
  items: const [
    BottomNavigationBarItem(
      icon: Icon(Icons.home),
      label: 'Home',
      backgroundColor: Colors.blue,
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.explore),
      label: 'Explore',
      backgroundColor: Colors.green,
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.favorite),
      label: 'Favorites',
      backgroundColor: Colors.red,
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.person),
      label: 'Profile',
      backgroundColor: Colors.purple,
    ),
  ],
  currentIndex: _selectedIndex,
  type: BottomNavigationBarType.shifting,
  onTap: _onItemTapped,
)

Shifting Type Features:

  • Background color changes with selected tab
  • Smooth animated transitions
  • Selected item grows larger
  • Best for 4-5 items

🔹 Complete Example

A full working bottom navigation implementation:

import 'package:flutter/material.dart';

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

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

class MainScreen extends StatefulWidget {
  @override
  _MainScreenState createState() => _MainScreenState();
}

class _MainScreenState extends State {
  int _currentIndex = 0;

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('My App'),
      ),
      body: _screens[_currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _currentIndex,
        onTap: (index) {
          setState(() {
            _currentIndex = index;
          });
        },
        type: BottomNavigationBarType.fixed,
        selectedItemColor: Colors.blue,
        unselectedItemColor: Colors.grey,
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.search),
            label: 'Search',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.notifications),
            label: 'Notifications',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: 'Profile',
          ),
        ],
      ),
    );
  }
}

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

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

class NotificationsScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(child: Text('Notifications Screen', style: TextStyle(fontSize: 24)));
  }
}

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

🧠 Test Your Knowledge

How many items should a Bottom Navigation Bar typically have?