user1666453
user1666453

Reputation: 23

Flutter - How to change state from inside another widget

I'm trying to implement both a Drawer and the Bottom Navigation Bar. The below class NavigationHomeScreen is my home screen and when the user clicks a menu item in the Drawer the Changeindex function updates the screenView I would like to know how I can similarly update the screenView but from the BottomNavigationBarApp using the onTabTapped method.

class NavigationHomeScreen extends StatefulWidget {
  @override
  _NavigationHomeScreenState createState() => _NavigationHomeScreenState();
}

class _NavigationHomeScreenState extends State<NavigationHomeScreen> {
  Widget screenView;
  DrawerIndex drawerIndex;

  @override
  void initState() {
    drawerIndex = DrawerIndex.HOME;
    screenView = const MyHomePage();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: AppTheme.nearlyWhite,
      child: SafeArea(
        top: false,
        bottom: false,
        child: Scaffold(
          appBar: emptyAppbar(),
          backgroundColor: AppTheme.nearlyWhite,
          body: DrawerUserController(
            screenIndex: drawerIndex,
            drawerWidth: MediaQuery.of(context).size.width * 0.75,
            onDrawerCall: (DrawerIndex drawerIndexdata) {
              changeIndex(drawerIndexdata);
              //callback from drawer for replace screen as user need with passing DrawerIndex(Enum index)
            },
            screenView: screenView,
            //we replace screen view as we need on navigate starting screens like MyHomePage, HelpScreen, FeedbackScreen, etc...
          ),
          bottomNavigationBar:BottomNavigationBarApp(context, 1),
        ),
      ),
    );
  }

  void changeIndex(DrawerIndex drawerIndexdata) {
    if (drawerIndex != drawerIndexdata) {
      drawerIndex = drawerIndexdata;
      if (drawerIndex == DrawerIndex.HOME) {
        setState(() {
          screenView = const MyHomePage();
        });
      } else if (drawerIndex == DrawerIndex.Help) {
        setState(() {
          screenView = HelpScreen();
        });
      } else if (drawerIndex == DrawerIndex.FeedBack) {
        setState(() {
          screenView = FeedbackScreen();
        });
      } else if (drawerIndex == DrawerIndex.Invite) {
        setState(() {
          screenView = InviteFriend();
        });
      } else {
        //do in your way......
      }
    }
  }
}
class BottomNavigationBarApp extends StatelessWidget {
  final int bottomNavigationBarIndex;
  final BuildContext context;

  const BottomNavigationBarApp(this. context, this.bottomNavigationBarIndex);

  void onTabTapped(int index) {

  }

  @override
  Widget build(BuildContext context) {
    return BottomNavigationBar(
      currentIndex: bottomNavigationBarIndex,
      type: BottomNavigationBarType.fixed,
      selectedFontSize: 10,
      selectedLabelStyle: TextStyle(color: CustomColors.BlueDark),
      selectedItemColor: CustomColors.BlueDark,
      unselectedFontSize: 10,
      items: [
        BottomNavigationBarItem(
          icon: Container(
            margin: EdgeInsets.only(bottom: 5),
            child: Image.asset(
              'assets/images/home.png',
              color: (bottomNavigationBarIndex == 1)
                  ? CustomColors.BlueDark
                  : CustomColors.TextGrey,
            ),
          ),
          title: Text('Home'),
        ),
        BottomNavigationBarItem(
          icon: Container(
            margin: EdgeInsets.only(bottom: 5),
            child: Image.asset(
              'assets/images/task.png',
              color: (bottomNavigationBarIndex == 0)
                  ? CustomColors.BlueDark
                  : CustomColors.TextGrey,
            ),
          ),
          title: Text('Appointments'),
        ),
      ],
      onTap: onTabTapped,
    );
  }
}

Upvotes: 1

Views: 2150

Answers (2)

eyoeldefare
eyoeldefare

Reputation: 2303

The best way to do it and also recommended by the Flutter development team is to use the provider package from flutter to manage the state between those widgets.

The top answer does solves your issue if its small app, but as your application grows, you most likely want to change things far up a widget tree which makes functions impractical.

Upvotes: 0

Benedikt J Schlegel
Benedikt J Schlegel

Reputation: 1939

You can pass a reference to a function down to a widget. Something like this:

In your HomeScreen:

 void updateScreenView() {
   //Do changes you want here. Dont forget to setState!
  }

In your BottomNavigationBarApp (edit: Function must start with a capital F):

  final int bottomNavigationBarIndex;
  final BuildContext context;
  final Function tapHandler;

  const BottomNavigationBarApp(this. context, this.bottomNavigationBarIndex, this.tapHandler);

and then just pass the reference on:

bottomNavigationBar:BottomNavigationBarApp(context, 1, updateScreenView),

And assign the function to your handler.

onTap: () => tapHandler(),

Upvotes: 1

Related Questions