Imagine I have a parent widget and a child widget. In the parent widget, there is a variable: 'page index'. And the child widget needs to change that variable in a set state method (because it has to be refreshed). How can I do this?
The body of the scaffold renders content based on the pageindex.
The code
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
int pageIndex = 0;
List<Widget> pageList = <Widget>[
HomeScreen(),
ProfileScreen(),
CartScreen(),
ProfileScreen(),
ProfileScreen()
];
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => CartViewModel()),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Home page',
theme: theme(),
onGenerateRoute: generateRoute,
home: Scaffold(
bottomNavigationBar: BottomNavBar(pageIndex, setPageIndex()),
body: pageList[pageIndex],
),
),
);
}
void setPageIndex(newValue) {
setState(() {
pageIndex = newValue;
});
}
}
class BottomNavBar extends StatefulWidget {
BottomNavBar(this.pageIndex, this.setPageIndexFunction);
int pageIndex;
VoidCallback setPageIndexFunction;
@override
State<BottomNavBar> createState() => _BottomNavBarState();
}
class _BottomNavBarState extends State<BottomNavBar> {
@override
Widget build(BuildContext context) {
CartViewModel cartViewModel = context.watch<CartViewModel>();
return BottomNavigationBar(
elevation: 5,
backgroundColor: Colors.white,
currentIndex: widget.pageIndex,
type: BottomNavigationBarType.fixed,
fixedColor: kAccentColor,
items: [
const BottomNavigationBarItem(
label: "Home", icon: Icon(Icons.home_outlined)),
const BottomNavigationBarItem(
label: "Search", icon: Icon(Icons.search_outlined)),
BottomNavigationBarItem(
label: "Cart",
icon: buildCustomBadge(
counter: cartViewModel.loading == false
? cartViewModel.cart!.count
: 0,
child: Icon(Icons.shopping_bag_outlined),
)),
const BottomNavigationBarItem(
label: "Favorite",
icon: Icon(Icons.favorite_border_outlined)),
const BottomNavigationBarItem(
label: "Profile", icon: Icon(Icons.person_outline))
],
onTap: (value) {
widget.setPageIndexFunction(value);
},
);
}
}
What is the problem
I am trying to call the function: "setPageIndexFunction(value)" and pass in the clicked value. Then it should call the function "setState" in the parent.
How can I do this? The reason I put the bottomnavbar in a separate widget is because I could not write this line of code in the MyApp class: "CartViewModel cartViewModel = context.watch();". I need this line to check if an item has been added to my cart and show it in the bottomnavbar.
Or should I use provider for this?
Thanks!
CodePudding user response:
Try these steps:
- Use
ValueChanged<int>
instead ofVoidCallback
class BottomNavBar extends StatefulWidget {
BottomNavBar(this.pageIndex, this.setPageIndexFunction);
int pageIndex;
ValueChanged<int> setPageIndexFunction;
@override
State<BottomNavBar> createState() => _BottomNavBarState();
}
- Use
setPageIndex
in_MyAppState
as a tear-off.
bottomNavigationBar: BottomNavBar(pageIndex, setPageIndex),