1

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!

Jay
  • 231
  • 1
  • 12
  • I have answered similar question here https://stackoverflow.com/questions/71250373/how-to-keep-bottom-navigation-bar-in-all-pages-with-stateful-widget-in-flutter/71250570#71250570 – Ante Bule Mar 15 '22 at 13:26
  • Hey, thanks! The answer from Josteven works fine. Thanks anyways :) – Jay Mar 15 '22 at 14:21

1 Answers1

2

Try these steps:

  1. Use ValueChanged<int> instead of VoidCallback
class BottomNavBar extends StatefulWidget {
  BottomNavBar(this.pageIndex, this.setPageIndexFunction);
  int pageIndex;
  ValueChanged<int> setPageIndexFunction;
  @override
  State<BottomNavBar> createState() => _BottomNavBarState();
}
  1. Use setPageIndex in _MyAppState as a tear-off.
  bottomNavigationBar: BottomNavBar(pageIndex, setPageIndex),
Josteve
  • 11,459
  • 1
  • 23
  • 35
  • Thanks! this works perfectly. I did not know ValueChanged existed. What were your google search terms to find that function? – Jay Mar 15 '22 at 14:21
  • I didn't google it...I was going through `TextField`'s `onChanged` property one day and I saw the type. – Josteve Mar 15 '22 at 14:54