I am trying to add a side menu and a bottom navigation bar to my flutter app. I have combined the code into the main_screen.dart file.
When I run the code, the bottom navigation bar works fine but if I tap on a side menu item I get this error:
_AssertionError ('package:flutter/src/material/bottom_navigation_bar.dart': Failed assertion: line 251 pos 15: '0 <= currentIndex && currentIndex < items.length': is not true.)
Here is the main_screen.dart code:
class MainScreenState extends State<MainScreen> {
final auth = FirebaseAuth.instance;
int _pageIndex = 0;
final List<Widget> appScreens = [
const CompanyDashboardScreen(),
const TransactionDetailScreen(true),
const AppointmentCalendarScreen(),
const UserProfileScreen(),
const ChatScreen(),
const CompanyScreen(),
const UserProfileScreen(),
];
Future<void> signOut() async {
await auth.signOut();
}
void onItemTapped(int index) {
setState(() {
_pageIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(),
body: Container(child: appScreens[_pageIndex]),
drawer: Drawer(
child: (ListView(
padding: EdgeInsets.zero,
children: [
const UserAccountsDrawerHeader(
accountName: Text('Billy Bob Baker'),
accountEmail: Text('billy.bob.baker@gmail.com'),
),
Container(
child: Column(
children: <Widget>[
ListTile(
title: const Text('Add Company'),
selected: _pageIndex == 5,
onTap: () {
// Update the state of the app
onItemTapped(5);
// Then close the drawer
Navigator.pop(context);
},
),
ListTile(
title: const Text('Add User'),
selected: _pageIndex == 6,
onTap: () {
// Update the state of the app
onItemTapped(6);
// Then close the drawer
Navigator.pop(context);
},
),
ListTile(
title: const Text('Log Out'),
selected: _pageIndex == 7,
onTap: () {
// Update the state of the app
signOut();
// Then close the drawer
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const LoginScreen()));
},
),
],
),
),
],
)),
),
bottomNavigationBar: BottomNavigationBar( <<< ERROR HERE
backgroundColor: Colors.blueAccent,
selectedIconTheme: const IconThemeData(color: Colors.white),
selectedItemColor: Colors.white,
unselectedItemColor: Colors.black45,
type: BottomNavigationBarType.fixed,
currentIndex: _pageIndex,
onTap: (value) {
setState(() {
_pageIndex = value;
});
},
items: const [
BottomNavigationBarItem(icon: Icon(Icons.home), label: "Home"),
BottomNavigationBarItem(
icon: Icon(Icons.add_business_outlined), label: "Trxn"),
BottomNavigationBarItem(
icon: Icon(Icons.calendar_today), label: "Calendar"),
BottomNavigationBarItem(icon: Icon(Icons.people), label: "User"),
BottomNavigationBarItem(icon: Icon(Icons.chat), label: 'Chat'),
],
),
);
}
// Added this for BottomNavigationBar sync
void setIndex(int index) {
if (mounted) setState(() => _pageIndex = index);
}
}
How do I combine the 2 navigation methods without having them interfere with each other?
Thanks
The ListTiles in your drawer can set the _pageIndex
to 5, 6, and 7 but there are only 5 items in your BottomNavigationBar (max valid index is 4).
I would suggest separating the logic of the drawer ListTiles from the BottomNavigationBar. In other words, don't let the drawer update the page index. Instead, tapping on a tile in the drawer should navigate to a new page.
You can reference this page to learn how navigation works in Flutter: https://docs.flutter.dev/cookbook/navigation/navigation-basics
ListTile(
title: const Text('Add User'),
onTap: () {
// Close the drawer
Navigator.pop(context);
// Navigate to new page
Navigator.push(
context,
MaterialPageRoute(builder: (context) =>
const SecondRoute()),
);
},
),