我正在尝试实现嵌套侧面导航,但是当某个项目具有子项目时,带有子项目的项目旁边的项目在单击时会显示错误的屏幕。该问题似乎与索引有关。因为下一个项目正在获取之前项目的子项目的索引。我在这上面花了很多时间。但我无法解决它。如果有人知道如何解决它,请告诉我。谢谢。代码如下:
class _MasterScreenState extends State<MasterScreen> {
int _selectedIndex = 0; // Track the selected index
late UserModel cUserModel;
late UserAppInstitutionModel cSelectedUserAppInstitution;
List<MenuList> currentDestinations = [];
Set<int> visibleSubMenus = {}; // Track visible submenus by index
void getUserData(BuildContext context) {
AuthenticationNotifier authenticationNotifier =
Provider.of<AuthenticationNotifier>(context, listen: false);
cUserModel = authenticationNotifier.getUser();
cSelectedUserAppInstitution =
authenticationNotifier.getSelectedUserAppInstitution();
}
void handleMenuTap(int index) {
setState(() {
final menu = currentDestinations[index];
// If the menu has submenus
if (menu.subMenus != null && menu.subMenus!.isNotEmpty) {
// Toggle the visibility of the submenus
if (visibleSubMenus.contains(index)) {
visibleSubMenus.remove(index); // Collapse submenu
} else {
visibleSubMenus.add(index); // Expand submenu
}
// Set selected index to the main menu
_selectedIndex = index;
} else {
// If it's a main menu item without submenus
_selectedIndex = index; // Select main menu item
visibleSubMenus.clear(); // Clear any visible submenus
}
});
}
void handleSubMenuTap(int mainMenuIndex, int subMenuIndex) {
setState(() {
// Calculate the position of the submenu in the list
int baseIndex = mainMenuIndex + 1; // Start after the main menu
// Count how many submenus are in the main menu
int subMenuCount = currentDestinations[mainMenuIndex].subMenus!.length;
// Set selected index based on submenu position
_selectedIndex = baseIndex + subMenuIndex; // Set selected index based on submenu
});
}
List<SideNavigationBarItem> getSideNavigationBarItem(BuildContext context) {
currentDestinations = destinations.where((menu) => menu.isVisible).toList();
List<SideNavigationBarItem> items = [];
// Iterate over main menu items
for (int i = 0; i < currentDestinations.length; i++) {
final menu = currentDestinations[i];
// Add the main menu item
items.add(SideNavigationBarItem(
icon: menu.icon,
label: menu.label,
));
// Check if the submenu should be visible
if (visibleSubMenus.contains(i) && menu.subMenus != null) {
// Add submenu items right after the main menu item
for (int j = 0; j < menu.subMenus!.length; j++) {
items.add(SideNavigationBarItem(
icon: menu.subMenus![j].icon, // Use submenu icon
label: menu.subMenus![j].label, // Submenu label
));
}
}
}
return items;
}
List<Widget> getScreenNavigationBarItem() {
List<Widget> screens = [];
// Add the main menu screens and their submenu screens
for (var menu in currentDestinations) {
screens.add(menu.screen); // Add main menu screen
if (menu.subMenus != null) {
for (var subMenu in menu.subMenus!) {
screens.add(subMenu.screen); // Add submenu screens
}
}
}
return screens;
}
@override
Widget build(BuildContext context) {
getUserData(context);
return Scaffold(
body: Row(
children: [
// Sidebar for main navigation
SideNavigationBar(
expandable: true,
theme: SideNavigationBarTheme.blue(),
footer: SideNavigationBarFooter(
label: Column(
children: [
Text(
'${cUserModel.name} ${cUserModel.surname}',
style: Theme.of(context).textTheme.headlineSmall,
),
Text(
cUserModel.email,
style: Theme.of(context).textTheme.headlineSmall,
),
Text(
cSelectedUserAppInstitution.roleUserAppInstitution,
style: Theme.of(context).textTheme.headlineSmall,
),
],
),
),
selectedIndex: _selectedIndex,
items: getSideNavigationBarItem(context), // Get menu with submenus
onTap: (index) {
// Calculate the current index of items
int currentIndex = 0; // Track the current index across all items (main and submenus)
for (int i = 0; i < currentDestinations.length; i++) {
final menu = currentDestinations[i];
// If this is the selected main menu
if (currentIndex == index) {
// Handle main menu taps
handleMenuTap(i);
return; // Exit the loop once the right menu is handled
}
currentIndex++; // Move to next menu item
// If this menu has visible submenus, we also need to account for those
if (visibleSubMenus.contains(i) && menu.subMenus != null) {
for (int j = 0; j < menu.subMenus!.length; j++) {
if (currentIndex == index) {
handleSubMenuTap(i, j); // Handle the tap for the submenu item
return;
}
currentIndex++; // Move to next submenu item
}
}
}
},
),
// Expanded area to display the selected content
Expanded(
child: LazyIndexedStack(
index: _selectedIndex, // Use the index to display the selected screen
children: getScreenNavigationBarItem(), // List of all screens
),
)
],
),
);
}
}
可以通过为主菜单项和子菜单项使用单独的索引变量来完成。如:
class _MasterScreenState extends State<MasterScreen> {
int _selectedMainMenuIndex = 0; // Track selected main menu index
int? _selectedSubMenuIndex; // Track selected submenu
// rest of your code
void handleMenuTap(int index) {
setState(() {
final menu = currentDestinations[index];
if (menu.subMenus != null && menu.subMenus!.isNotEmpty) {
if (visibleSubMenus.contains(index)) {
visibleSubMenus.remove(index); // Collapse submenu
} else {
visibleSubMenus.add(index); // Expand submenu
}
_selectedMainMenuIndex = index;
_selectedSubMenuIndex = null; // Clear any selected submenu
} else {
_selectedMainMenuIndex = index;
_selectedSubMenuIndex = null;
visibleSubMenus.clear(); // Collapse all submenus
}
});
}
void handleSubMenuTap(int mainMenuIndex, int subMenuIndex) {
setState(() {
_selectedMainMenuIndex = mainMenuIndex;
_selectedSubMenuIndex = subMenuIndex; // Track submenu index
});
}
List<SideNavigationBarItem> getSideNavigationBarItems(BuildContext context) {
currentDestinations = destinations.where((menu) => menu.isVisible).toList();
List<SideNavigationBarItem> items = [];
// Iterate over main menu items
for (int i = 0; i < currentDestinations.length; i++) {
final menu = currentDestinations[i];
// Add main menu item
items.add(SideNavigationBarItem(
icon: menu.icon,
label: menu.label,
));
// Add submenu items if they are visible
if (visibleSubMenus.contains(i) && menu.subMenus != null) {
for (int j = 0; j < menu.subMenus!.length; j++) {
items.add(SideNavigationBarItem(
icon: menu.subMenus![j].icon,
label: menu.subMenus![j].label,
));
}
}
}
return items;
}
Widget getSelectedScreen() {
final mainMenu = currentDestinations[_selectedMainMenuIndex];
if (_selectedSubMenuIndex != null) {
return mainMenu.subMenus![_selectedSubMenuIndex!].screen;
}
return mainMenu.screen;
}
@override
Widget build(BuildContext context) {
AuthenticationNotifier authenticationNotifier =
Provider.of<AuthenticationNotifier>(context, listen: true);
cUserModel = authenticationNotifier.getUser();
cSelectedUserAppInstitution = authenticationNotifier.getSelectedUserAppInstitution();
// Display a loading state while data is being fetched
if (cUserModel == null || cSelectedUserAppInstitution == null) {
return const Center(child: CircularProgressIndicator()); // Show loading spinner until data is available
}
footer: SideNavigationBarFooter(
label: Column(
children: [
Text(
'${cUserModel!.name} ${cUserModel!.surname}', // Safely unwrap nullable values
style: Theme.of(context).textTheme.headlineSmall,
),
Text(
cUserModel!.email, // Safely unwrap nullable value
style: Theme.of(context).textTheme.headlineSmall,
),
Text(
cSelectedUserAppInstitution!.roleUserAppInstitution, // Safely unwrap
style: Theme.of(context).textTheme.headlineSmall,
),
],
),
),
selectedIndex: _selectedSubMenuIndex == null
? _selectedMainMenuIndex
: _selectedMainMenuIndex + 1 + _selectedSubMenuIndex!,
items: getSideNavigationBarItems(context),
onTap: (index) {
int currentIndex = 0;
for (int i = 0; i < currentDestinations.length; i++) {
final menu = currentDestinations[i];
if (currentIndex == index) {
handleMenuTap(i);
return;
}
currentIndex++;
if (visibleSubMenus.contains(i) && menu.subMenus != null) {
for (int j = 0; j < menu.subMenus!.length; j++) {
if (currentIndex == index) {
handleSubMenuTap(i, j);
return;
}
currentIndex++;
}
}
}
},
),
// Expanded area to display the selected content
Expanded(
child: getSelectedScreen(),
),
],
),
);
}
}