I have the following navigation bar in my flutter app:
BottomNavigationBar(
items: [
const BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: appState.itemCard.cardItems.isNotEmpty // only show Badge when items are cardItems
? badges.Badge( // This is the Badge
badgeContent: Text(appState
.itemCard.cardItems.values
.reduce((a, b) => a + b)
.toString()),
child: const Icon(Icons.shopping_cart),
)
: const Icon(Icons.shopping_cart),
label: 'Card',
),
const BottomNavigationBarItem(
icon: Icon(Icons.menu),
label: 'Menu',
),
],
currentIndex: selectedIndex,
onTap: (value) {
setState(() {
selectedIndex = value;
});
},
)
The issue is that when I make changes to the itemCard.cardItems
the badge count doesn't update until I click on another NavigationBarItem
like Home
.
How can I achieve that the badge updates immediately when I add items to the itemCard.cardItems
?
I've created a ValueNotifier
for the value in the ItemCard
Class:
class ItemCard {
Map<Item, int> cardItems = {};
double totalPrice = 0.0;
ValueNotifier<int> totalItems = ValueNotifier<int>(0); // <-- this one
}
In the next step I wrapped the icon of the corresponding BottomNavigationBarItem
with the ValueListenableBuilder
:
BottomNavigationBarItem(
icon: ValueListenableBuilder( // wrapped Icon
builder: (context, value, child) => badges.Badge(
showBadge:
appState.itemCard.totalItems.value > 0,
badgeContent: Text(appState
.itemCard.totalItems.value
.toString()),
child: const Icon(Icons.shopping_cart),
),
valueListenable: appState.itemCard.totalItems), // ValueNotifier
label: 'Card',
),
Suppose you have
List<CartModel> appState.itemCard.cardItems =[]
in your AppState file
Replace it to
ValueNotifier<List<CartModel>> appState.itemCard.cardItems =ValueNotifier<List<CartModel>>([]);
And replace
BottomNavigationBarItem(
icon: appState.itemCard.cardItems.isNotEmpty // only show Badge when items are cardItems
? badges.Badge( // This is the Badge
badgeContent: Text(appState
.itemCard.cardItems.values
.reduce((a, b) => a + b)
.toString()),
child: const Icon(Icons.shopping_cart),
)
: const Icon(Icons.shopping_cart),
label: 'Card',
),
to
ValueListenableBuilder(builder : (BuildContext context, int value, Widget? child) {
// This builder will only get called when the _counter
// is updated.
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text('$value'),
child!,
],
);},valueListenable: appState
.itemCard.cardItems)
if you are already using ValueNotifier then just wrap your widget with ValueListenableBuilder
For More https://api.flutter.dev/flutter/widgets/ValueListenableBuilder-class.html