Chapter 6.6 Do I understand ... Adding a TabManager consumer?

I want to see if I understand the below code in BottomNavigationBar() … If I do, I’ll be amazed :grinning: … How close am I?

  • Immediately after pressing one of the tabs at the bottom of the screen, the currentIndex property of the BottomNavigationBar contains the index (0-2) of the tab that was selected and that we’re about to go to.
  • At that point, onTap: (index) causes the variable index to be set to currentIndex which is also the value of selectedTab.
  • tabManager.goToTab (index) causes tabManager to notify the listeners.
  • I think both uses of index could be replaced by either selectedTab or currentIndex.
  • The line body: pages[tabManager.selectedTab], could be replaced by body: pages[selectedTab], except that the listeners wouldn’t be notified and the state wouldn’t change and the pages wouldn’t actually switch.

What I’m not clear about is this line:

currentIndex: tabManager.selectedTab,

I just don’t understand what tabManager.selectedTab is … selectedTab isn’t a property or method, is it?

bottomNavigationBar: BottomNavigationBar(
            selectedItemColor:
                Theme.of(context).textSelectionTheme.selectionColor,
            // 3
            currentIndex: tabManager.selectedTab,
            onTap: (index) {
              // 4
              tabManager.goToTab(index);
            },
            items: <BottomNavigationBarItem>[
              const BottomNavigationBarItem(
                icon: Icon(Icons.explore),
               label: 'Explore',
              ),
              const BottomNavigationBarItem(
                icon: Icon(Icons.book),
                label: 'Recipes',
              ),
              const BottomNavigationBarItem(
                icon: Icon(Icons.list),
                label: 'To Buy',
              ),
            ],

@jefff9511 i think you understand pretty well! Seems like you are making awesome progress!

Chapter 6 briefly introduces the provider package that you will learn in Chapter 13. It doesn’t hurt to jump to Chapter 13 to get a quick overview either :).

selectedTab is a property of TabManager, it will let you know which tab the user has selected. The idea is to only have TabManager manage selectedTab state property through two functions.

  1. goToTab, with a given index
  2. goToRecipes, set selectedTab to Recipes tab’s index.
class TabManager extends ChangeNotifier {
  // 2
  int selectedTab = 0;

  // 3
  void goToTab(index) {
    // 4
    selectedTab = index;
    // 5
    notifyListeners();
  }

  // 6
  void goToRecipes() {
    selectedTab = 1;
    // 7
    notifyListeners();
  }
}

TabManager is used in three places:

  1. To control bottomNavigationBar’s index, to show the appropriate highlighted tab. The sole purpose of bottomNavigationBar is to display tab item, and currentIndex lets you know which one to highlight.
  2. To control which page is shown based on the selectedTab.
  3. To navigate from another screen to Recipes tab.

Screen Shot 2021-10-22 at 8.25.44 AM

TabManager() is provided at the root level of the widget tree, please check out main.dart.

Next in home.dart you will notice the Home widget is wrapped in a Consumer widget. When TabManager notifies its listeners, the builder function gets trigger again with the updated selectedTab index.

Think of this as a single direction flow of data.

  • Display current value to the user
  • User performs some action (Tapping on a tab or button)
  • TabManager updates the state and notify listeners
  • Widget redraws

Hope this is helpful

1 Like

Thanks @jomoka … Here’s a critical piece that I’m missing … Maybe I got lost in an earlier chapter:

If selectedTab is a property of TabManager, whouldn’t it have to be defined in a constructor something like TabManager (this.selectedTab);?

I’ve heard of getters and setters but don’t know anything about them. Is that what this is? If so, have we discussed them yet?

@jefff9511 in this chapter there is no constructor to set the selectedTab. The initial tab will always be zero. However that doesn’t stop you from adding a constructor to pass in your own index. Whatever works for what you build in the future.

selectedTab property includes both the getter and setter.

For more information about how to only include getter or setter you can check out the dart apprentice book or check out the section on getter and setter here:

OK … I finally figured out why I’m confused by tabManager.selectedTab. Somewhere along the line, I didn’t understand that you could access the property of a class using this syntax.

I thought you always had to specify it by tabManager(selectedTab) which I now understand is only to create a new instance of TabManager with a value of selectedTab.

The tabManager.selectedTab syntax passes the value of selectedTab to TabManager without creating a new instance of TabManager.

Do I have that right?

@jefff9511 selectedTab is a property within tab manager. SelectedTab is not passed in to the manager at all.

Just like the postId is part of the post object