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:
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
);
}
}