I am using showMenu() function to create and render a menu when onTap() on a certain ListTile widget. So, How to make the ListTile show in an active/inactive state (using some background colour) when the menu is active and vice versa.
PS. I am able to achieve active state when the list tile is clicked using onTap() but unable to achieve the inactive state as I am unable to find a way of reverting the `List Tile background colour because there is no toggle/function when the pop-up menu from show menu is closed.
Please check the below images to get more clarity on the issue.
inactive state
active and menu open
menu closed but colour is still in effect
// List to maintain active states (item will be pushed to list on onTap() function)
List sideOptions = [];
// function to return color w.r.t if statements
Color changeBackground(bool isHovered, String sideOption) {
print(currentRoute);
if ((isHovered || (currentRoute == "/$sideOption")) ||
sideOptions.contains(sideOption)) {
return global_styles.blueShade;
} else {
return Colors.transparent;
}
}
// ListTile wrapped in a container
// OnHoverIcon() is a function i wrote to capture hover events if any
// ListTile onTap() function
_buildPopUpMenuButton(
String title, String iconString, List<PopupMenuEntry> subItems) {
child: OnHoverIcon(builder: (isHovered) {
return Container(
height: 55,
decoration: BoxDecoration(
color: changeBackground(isHovered, title),
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(8.0),
topRight: Radius.circular(8.0),
),
),
child: ListTile(
onTap: () => {
sideOptions.add(title),
if (!_isDropdownOpen)
{_controller.forward(), _isDropdownOpen = true}
else
{
_controller.reverse(),
_isDropdownOpen = false,
},
// _isDropdownOpen = true,
showMenu(
context: context,
position: getSizeandPosition(),
items: subItems)
},
leading: Image.asset(
iconString,
color: changeIconColors(isHovered, title),
),
title: Text(
title,
style: sideNavItems(isHovered, title),
),
trailing: title != "Settings"
? RotationTransition(
turns: _rotationAnimation,
child: Icon(
Icons.keyboard_arrow_up,
color: changeIconColors(isHovered, title),
),
)
: null,
),
);
}
);
}
}`
CodePudding user response:
showMenu()
returns a Future
that ends when the menu is popped. So, you can place an await
before it and it'll continue to the next line when the menu is popped.
Like this:
void onTap() async {
// Set the tile as active (changes the color to blue)
setState(() {
isActive = true;
});
// Show menu and wait for it to pop.
await showMenu(
/* ... */
);
// Menu is popped. Set the tile as inactive and return to the default color.
setState(() {
isActive = false;
});
}
Edit: It's best to extract the button to its own StatefulWidget
so setState()
will update just the button instead of the whole page.
If this doesn't work with your code. Maybe place a stateful widget in the menu and use dispose()
to detect when it's no longer active and trigger the inactivation method.