Home > Mobile >  Why is my app crashing when I try to implement my bottom navigation bar in Flutter?
Why is my app crashing when I try to implement my bottom navigation bar in Flutter?

Time:12-29

I am trying to implement a bottomNavigationBar that goes to different pages. So far, I have made the bulk of everything, which you can see in my code below.

Here is my bottomNavigationBar code in navBar.dart:

// ignore: file_names
import 'package:bottom_navy_bar/bottom_navy_bar.dart';
import 'package:flutter/material.dart';

import '../views/home_page.dart';
import '../views/secondScreen.dart';

// ignore: camel_case_types
class navBar extends StatefulWidget {
  const navBar({Key? key}) : super(key: key);

  @override
  State<navBar> createState() => _navBarState();
}

// ignore: camel_case_types
class _navBarState extends State<navBar> {
  int currentIndex = 0;
  final screens = [
    const HomePage(),
    const SecondRoute(),
    const SecondRoute(),
    const SecondRoute(),
  ];

  @override
  Widget build(BuildContext context) {
    screens[currentIndex];
    return BottomNavyBar(
      animationDuration: const Duration(milliseconds: 260),
      curve: Curves.ease,
      showElevation: false,
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      selectedIndex: currentIndex,
      onItemSelected: (index) {
        setState(() {
          currentIndex = index;
        });
        // Push the new page onto the navigation stack
        // Navigator.push(
        //   context,
        //   MaterialPageRoute(builder: (context) => pages[index]),
        // );
      },
      items: <BottomNavyBarItem>[
        BottomNavyBarItem(
          inactiveColor: const Color.fromARGB(255, 20, 143, 199),
          activeColor: const Color.fromARGB(255, 5, 176, 255),
          textAlign: TextAlign.center,
          icon: const Icon(Icons.home),
          title: const Text('Home'),
        ),
        BottomNavyBarItem(
          inactiveColor: const Color.fromARGB(255, 20, 143, 199),
          activeColor: const Color.fromARGB(255, 5, 176, 255),
          textAlign: TextAlign.center,
          icon: const Icon(Icons.discord),
          title: const Text('Discord'),
        ),
        BottomNavyBarItem(
          inactiveColor: const Color.fromARGB(255, 20, 143, 199),
          activeColor: const Color.fromARGB(255, 5, 176, 255),
          textAlign: TextAlign.center,
          icon: const Icon(Icons.school),
          title: const Text('Examotron'),
        ),
        BottomNavyBarItem(
          inactiveColor: const Color.fromARGB(255, 20, 143, 199),
          activeColor: const Color.fromARGB(255, 5, 176, 255),
          textAlign: TextAlign.center,
          icon: const Icon(Icons.document_scanner),
          title: const Text('Notes'),
        ),
      ],
    );
  }
}

And here is my home page home_page.dart:

import 'package:xconcordia/services/remote_service.dart';
import 'package:flutter/material.dart';
import 'package:xconcordia/views/secondScreen.dart';
import 'package:xconcordia/widgets/categoryPicker.dart';
import '../widgets/libraryCards.dart';
import '../widgets/libraryStatsHeader.dart';
import '../widgets/navBar.dart';

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

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

var webb = '';
String webOccupancy = '';
String greyOccupancy = '';
String vannierOccupancy = '';
String libTime = '';
String webLevel = '';
String greyLevel = '';
String vannierLevel = '';

class _HomePageState extends State<HomePage> {
  bool isLoading = false;
  int currentIndex = 1;

  // List of pages
  List<Widget> pages = [
    const HomePage(),
    const SecondRoute(),
    const SecondRoute(),
    const SecondRoute(),
  ];
  @override
  void initState() {
    super.initState();
    _fetchWebOccupancy();
    _fetchVannierOccupancy();
    _fetchGreyOccupancy();
    _fetchLibTime();
  }

  Future<void> _fetchLibTime() async {
    if (libTime == '') {
      String? libraryTime = await getDataAPI_time().getPosts();
      setState(() {
        libTime = libraryTime.toString();
      });
    }
  }

  Future<void> _fetchWebOccupancy() async {
    if (webOccupancy == '') {
      String? occupancy = await getDataAPI().getPosts();
      setState(() {
        webOccupancy = occupancy!.substring(0, occupancy.length - 5);
        if (webOccupancy == '' || int.parse(webOccupancy) < 0) {
          webOccupancy = '0';
        }
        if (int.parse(webOccupancy) > 100) {
          webLevel = 'High';
        } else if (int.parse(webOccupancy) > 75 &&
            int.parse(webOccupancy) < 100) {
          webLevel = 'Medium';
        } else {
          webLevel = 'Low';
        }
        isLoading = false;
      });
    }
  }

  Future<void> _fetchGreyOccupancy() async {
    if (greyOccupancy == '') {
      String? occupancy = await getDataAPI_G().getPosts();
      setState(() {
        greyOccupancy = occupancy!.substring(0, occupancy.length - 5);
        if (greyOccupancy == '' || int.parse(greyOccupancy) < 0) {
          greyOccupancy = '0';
        }
        if (int.parse(greyOccupancy) > 100) {
          greyLevel = 'High';
        } else if (int.parse(greyOccupancy) > 50 &&
            int.parse(greyOccupancy) < 100) {
          greyLevel = 'Medium';
        } else {
          greyLevel = 'Low';
        }
        isLoading = false;
      });
    }
  }

  Future<void> _fetchVannierOccupancy() async {
    if (vannierOccupancy == '') {
      String? occupancy = await getDataAPI_V().getPosts();
      setState(() {
        vannierOccupancy = occupancy!.substring(0, occupancy.length - 5);
        if (vannierOccupancy == '' || int.parse(vannierOccupancy) < 0) {
          vannierOccupancy = '0';
        }
        if (int.parse(vannierOccupancy) > 100) {
          vannierLevel = 'High';
        } else if (int.parse(vannierOccupancy) > 50 &&
            int.parse(vannierOccupancy) < 100) {
          vannierLevel = 'Medium';
        } else {
          vannierLevel = 'Low';
        }
        isLoading = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.transparent,
        // elevation: 15,
        // leading: IconButton(
        //   icon: const Icon(Icons.menu),
        //   onPressed: () {},
        // ),

        title: const Text('xConcordia'),
        flexibleSpace: Container(
          decoration: const BoxDecoration(
            boxShadow: [
              BoxShadow(
                color: Color.fromARGB(223, 57, 25, 163),
                offset: Offset(0, 0),
                blurRadius: 20,
              ),
            ],
            gradient: LinearGradient(
              begin: Alignment.topLeft,
              end: Alignment.bottomRight,
              colors: [Colors.blue, Colors.purple],
            ),
          ),
        ),
      ),
      body: isLoading
          ? const Center(
              child: LinearProgressIndicator(
              color: Color.fromARGB(162, 114, 68, 251),
            ))
          : Container(
              margin: const EdgeInsets.only(top: 20),
              child: Column(
                children: [
                  // ignore: prefer_const_constructors
                  LibraryStatsHeader(), //LibraryStatsHeader widget is in a file called libraryStatsHeader
                  const Padding(padding: EdgeInsets.all(10)),
                  libCards(), //libCards widget is in a file called libraryCards
                  const categoryPicker(), //category picker
                ],
              ),
            ),
      bottomNavigationBar: const navBar(),
    );
  }
}

The issue in the above code is, despite my nav bar working (as in, clicking it changes the nav bar icons), the page state does not change (i.e, it doesn't go to another page, stays on the current page)

Now, I realize that I'm not doing anything with my screens [] array, so I should use that, and so in my navBar.dart, I thought to return body: screens[currentIndex] to make this logic work, so my nav bar is functional.

So, in this navBar.dart file, I surrounded the return with a Scaffold and did just that:

  Widget build(BuildContext context) {
      return Scaffold(
      body: screens[currentIndex],
      bottomNavigationBar: BottomNavyBar(
        animationDuration: const Duration(milliseconds: 250),
        curve: Curves.ease,
        showElevation: false,
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        selectedIndex: currentIndex,
        onItemSelected: (index) {
          setState(() {
            currentIndex = index;
          });
          // Push the new page onto the navigation stack
          // Navigator.push(
          //   context,
          //   MaterialPageRoute(builder: (context) => pages[index]),
          // );
        },
        items: <BottomNavyBarItem>[
          BottomNavyBarItem(
            inactiveColor: const Color.fromARGB(255, 20, 143, 199),
            activeColor: const Color.fromARGB(255, 5, 176, 255),
            textAlign: TextAlign.center,
            icon: const Icon(Icons.home),
            title: const Text('Home'),
          ),
          BottomNavyBarItem(
            inactiveColor: const Color.fromARGB(255, 20, 143, 199),
            activeColor: const Color.fromARGB(255, 5, 176, 255),
            textAlign: TextAlign.center,
            icon: const Icon(Icons.discord),
            title: const Text('Discord'),
          ),
          BottomNavyBarItem(
            inactiveColor: const Color.fromARGB(255, 20, 143, 199),
            activeColor: const Color.fromARGB(255, 5, 176, 255),
            textAlign: TextAlign.center,
            icon: const Icon(Icons.school),
            title: const Text('Examotron'),
          ),
          BottomNavyBarItem(
            inactiveColor: const Color.fromARGB(255, 20, 143, 199),
            activeColor: const Color.fromARGB(255, 5, 176, 255),
            textAlign: TextAlign.center,
            icon: const Icon(Icons.document_scanner),
            title: const Text('Notes'),
          ),
        ],
      ),
    );
  }

Doing this, I get an infinite loop of the same error:

Error

What is flawed in my logic when I try to return the Scaffold with the screens[currentIndex] as the body? Is it wrong? How else would I get this navigation bar working?

EDIT: I have added nav bar to my main.dart file, replacing home: HomePage() with navBar():

import 'package:flutter/material.dart';
import '../widgets/navBar.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: navBar(),
    );
  }
}

Yet, I still get the same error.

CodePudding user response:

In your homePage(), remove list of pages, currentIndex and bottom navBar. Your homePage() should look like this:

import 'package:flutter/material.dart';

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

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

var webb = '';
String webOccupancy = '';
String greyOccupancy = '';
String vannierOccupancy = '';
String libTime = '';
String webLevel = '';
String greyLevel = '';
String vannierLevel = '';

class _HomePageState extends State<HomePage> {
  bool isLoading = true;
  @override
  void initState() {
    super.initState();
    _fetchWebOccupancy();
    _fetchVannierOccupancy();
    _fetchGreyOccupancy();
    _fetchLibTime();
  }

  Future<void> _fetchLibTime() async {
    if (libTime == '') {
      String? libraryTime = await getDataAPI_time().getPosts();
      setState(() {
        libTime = libraryTime.toString();
      });
    }
  }

  Future<void> _fetchWebOccupancy() async {
    if (webOccupancy == '') {
      String? occupancy = await getDataAPI().getPosts();
      setState(() {
        webOccupancy = occupancy!.substring(0, occupancy.length - 5);
        if (webOccupancy == '' || int.parse(webOccupancy) < 0) {
          webOccupancy = '0';
        }
        if (int.parse(webOccupancy) > 100) {
          webLevel = 'High';
        } else if (int.parse(webOccupancy) > 75 &&
            int.parse(webOccupancy) < 100) {
          webLevel = 'Medium';
        } else {
          webLevel = 'Low';
        }
        isLoading = false;
      });
    }
  }

  Future<void> _fetchGreyOccupancy() async {
    if (greyOccupancy == '') {
      String? occupancy = await getDataAPI_G().getPosts();
      setState(() {
        greyOccupancy = occupancy!.substring(0, occupancy.length - 5);
        if (greyOccupancy == '' || int.parse(greyOccupancy) < 0) {
          greyOccupancy = '0';
        }
        if (int.parse(greyOccupancy) > 100) {
          greyLevel = 'High';
        } else if (int.parse(greyOccupancy) > 50 &&
            int.parse(greyOccupancy) < 100) {
          greyLevel = 'Medium';
        } else {
          greyLevel = 'Low';
        }
        isLoading = false;
      });
    }
  }

  Future<void> _fetchVannierOccupancy() async {
    if (vannierOccupancy == '') {
      String? occupancy = await getDataAPI_V().getPosts();
      setState(() {
        vannierOccupancy = occupancy!.substring(0, occupancy.length - 5);
        if (vannierOccupancy == '' || int.parse(vannierOccupancy) < 0) {
          vannierOccupancy = '0';
        }
        if (int.parse(vannierOccupancy) > 100) {
          vannierLevel = 'High';
        } else if (int.parse(vannierOccupancy) > 50 &&
            int.parse(vannierOccupancy) < 100) {
          vannierLevel = 'Medium';
        } else {
          vannierLevel = 'Low';
        }
        isLoading = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.transparent,
        // elevation: 15,
        // leading: IconButton(
        //   icon: const Icon(Icons.menu),
        //   onPressed: () {},
        // ),

        title: const Text('xConcordia'),
        flexibleSpace: Container(
          decoration: const BoxDecoration(
            boxShadow: [
              BoxShadow(
                color: Color.fromARGB(223, 57, 25, 163),
                offset: Offset(0, 0),
                blurRadius: 20,
              ),
            ],
            gradient: LinearGradient(
              begin: Alignment.topLeft,
              end: Alignment.bottomRight,
              colors: [Colors.blue, Colors.purple],
            ),
          ),
        ),
      ),
      body: isLoading
          ? const Center(
          child: LinearProgressIndicator(
            color: Color.fromARGB(162, 114, 68, 251),
          ))
          : Container(
        margin: const EdgeInsets.only(top: 20),
        child: Column(
          children: [
            // ignore: prefer_const_constructors
            LibraryStatsHeader(), //LibraryStatsHeader widget is in a file called libraryStatsHeader
            const Padding(padding: EdgeInsets.all(10)),
            libCards(), //libCards widget is in a file called libraryCards
            const categoryPicker(), //category picker
            
          ],
        ),
      ),
      
    );
  }
}

Do not add bottomNavigation to the list of pages like homePage(), secondRoute(), etc.

CodePudding user response:

Try this in Scaffold

return Scaffold(
  body: screens.elementAt(currentIndex),
  bottomNavigationBar: BottomNavyBar(

Remove bottomNavigationBar: const navBar() from homepage

Call navBar class in home of main.dart file as below

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

class MyApp extends StatelessWidget {
 const MyApp({super.key});

// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return const MaterialApp(
  title: 'Flutter Demo',
  debugShowCheckedModeBanner: false,
  home: navBar(), <------ here
 );
}
}
  • Related