Search code examples
flutterdartnavigation

Placement of NavigationBar widget in main.dart


I have a couple of questions. I am trying to add a navigation bar at the bottom of my flutter app. I have created a widget for the navigation bar and include it in my main.dart file.

I am using the NavigationBar and not the BottomNavigationBar.

This is my Main.dart file:

import 'package:flutter/material.dart';
import 'screens/home_screen.dart';
import 'screens/start_screen.dart';
import 'screens/widgets/bottom_nav_bar.dart';
import 'screens/map_screen.dart';

final List<Widget> appScreens = [
  const HomeScreen(),
  const StartScreen(),
  const MapPropertySearchResults(),
];

void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          backgroundColor: const Color.fromARGB(255, 2, 94, 252),
          title: const Center(
              child: Text(
            'Verical Reach',
            style: TextStyle(color: Colors.black, fontSize: 20),
          )),
        ),
        body: Container(
          decoration: const BoxDecoration(
            gradient: LinearGradient(
              colors: [Color.fromARGB(255, 2, 94, 252), Colors.yellowAccent],
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter,
            ),
          ),
          child: const appScreens.elementAt(selectedTab), <<<  ERROR HERE
        ),
        bottomNavigationBar: const BottomNav(),
      ),
    ),
  );
}

My Navigation Bar file:

import 'package:flutter/material.dart';
import 'package:for_testing/screens/start_screen.dart';
import '../map_screen.dart';
import '../tax_data_screen.dart';
import '../home_screen.dart';

class BottomNav extends StatefulWidget {
  const BottomNav({super.key});

  @override
  State<BottomNav> createState() {
    return _BottomNavState();
  }
}

class _BottomNavState extends State<BottomNav> {
  int selectedTab = 0;

  @override
  Widget build(BuildContext context) {
    return NavigationBar(
        onDestinationSelected: (int index) {
          setState(() {
            selectedTab = index;
          });
        },
        indicatorColor: Colors.amber,
        selectedIndex: selectedTab,
        destinations: const <Widget>[
          NavigationDestination(
            selectedIcon: Icon(Icons.home),
            icon: Icon(Icons.home_outlined),
            label: 'Home',
          ),
          NavigationDestination(
            icon: Icon(Icons.data_usage),
            label: 'Data',
          ),
          NavigationDestination(
            selectedIcon: Icon(Icons.map),
            icon: Icon(Icons.maps_ugc),
            label: 'Map',
          ),
        ],
      );
  }
}

You can see on this line I include the BottomNav widget. This seems to work fine and I am able to click on the different icons and see change.

My Questions:

  1. Is Main.dart the best place to put a bottom navigation bar? I want it to always be visible.

  2. I don't know how write the code so that when I click on an icon the screen will change to another screen. I have the code in the Main.dart file like this: child: const appScreens.elementAt(selectedTab), but I get an error. I don't think this is the right way to do this.

Thanks for your help


Solution

    1. Create a Separate Page for displaying Pages.
    2. Yes, it's not the right way to do this. and the error is occurring cos you're trying to use selectedTab var, which cannot be accessed as it is in BottomNav Widget class.

    To Do it in right way use the following code:

    Create a MainPage:

    class MainPage extends StatefulWidget {
      const MainPage({super.key});
    
      @override
      State<MainPage> createState() => _MainPageState();
    }
    
    class _MainPageState extends State<MainPage> {
      int selectedPage = 0;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(),
          body: yourPageList.elementAt(selectedPage), //eg: [HomePage(),Profile(),Settings()]
          bottomNavigationBar: BottomNav(
            selectedPage: selectedPage,
            onDestinationSelected: (index) {
              setState(() {
                selectedPage = index;
              });
            },
          ),
        );
      }
    }
    

    BottomNav Widget:

    class BottomNav extends StatelessWidget {
      final int selectedPage;
      final void Function(int) onDestinationSelected;
    
      const BottomNav(
          {super.key,
          required this.selectedPage,
          required this.onDestinationSelected});
    
      @override
      Widget build(BuildContext context) {
        return NavigationBar(
          onDestinationSelected: (int index) {
            onDestinationSelected(index);
          },
          indicatorColor: Colors.amber,
          selectedIndex: selectedPage,
          destinations: const <Widget>[
            NavigationDestination(
              selectedIcon: Icon(Icons.home),
              icon: Icon(Icons.home_outlined),
              label: 'Home',
            ),
            NavigationDestination(
              icon: Icon(Icons.data_usage),
              label: 'Data',
            ),
            NavigationDestination(
              selectedIcon: Icon(Icons.map),
              icon: Icon(Icons.maps_ugc),
              label: 'Map',
            ),
          ],
        );
      }
    }