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('[email protected]'),
),
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
2
Answers
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
For combining a side menu and a bottom navigation bar, a Scaffold with a Drawer for the side menu and a BottomNavigationBar for the bottom navigation bar should be used. The structure for the build method: