Search code examples
flutterdynamicbottom-navigation-bar

flutter dynamic navigation bar: identify which icon/button is tapped


I am creating a dynamic list of BottomNavigationBarItem and assigning it to 'items' of BottomNavigationBar. So based on a condition (here is my case, checks and add one more BottomNavigationBarItem if it is not billed. So the number of Icons displayed change. Normally for a fixed number of items, ontap provide index of the icon tapped. As the order/sequence of icons change, their index also differs.

Now how do I read the label of selected BottomNavigationBarItem and respond in onTap handler instead of tapped index value ?

(Of course in this particular case, I can add the additional button as last one and done with. Need a better solution.)

  List<BottomNavigationBarItem> getNavbarItems() {
    List<BottomNavigationBarItem> navItems = [];
    navItems.add(
      const BottomNavigationBarItem(
          icon: Icon(Icons.delete_outline,), label: 'Delete',),
    );
    if (widget.invStatus.isBilled == 0) {
      navItems.add(
        const BottomNavigationBarItem(
            icon: Icon(Icons.receipt), label: 'Bill it ?'),
      );
    }
    navItems.add(
      const BottomNavigationBarItem(
          icon: Icon(Icons.category_rounded), label: 'Add a Product !'),
    );
    return navItems;
  }

Thanks.


Solution

  • If I understand you correctly, you can use the following approach to get the "label".

    Call:

    getNavbarItems()[index].label
    

    And have a button to dynamically toggle isBilled.

    Complete example:

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            body: Center(
              child: Nav(),
            ),
          ),
        );
      }
    }
    
    class Nav extends StatefulWidget {
      @override
      createState() => NavState();
    }
    
    class NavState extends State<Nav> {
      var _selectedIndex = 0;
      var billIt = false;
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Nav'),
          ),
          body: Center(
            child: TextButton(
              child: Text('Toggle `billIt`'),
              onPressed: () {
                setState(() {
                  billIt = !billIt;
                });
              },
            ),
          ),
          bottomNavigationBar: BottomNavigationBar(
            currentIndex: _selectedIndex,
            items: getNavbarItems(),
            onTap: (int index) {
              setState(() {
                _selectedIndex = index;
                print('label: ${getNavbarItems()[index].label}');
              });
            },
          ),
        );
      }
    
      List<BottomNavigationBarItem> getNavbarItems() {
        List<BottomNavigationBarItem> navItems = [];
    
        navItems.add(
          const BottomNavigationBarItem(
            icon: Icon(
              Icons.delete_outline,
            ),
            label: 'Delete',
          ),
        );
    
        if (billIt) {
          navItems.add(
            const BottomNavigationBarItem(
                icon: Icon(Icons.receipt), label: 'Bill it ?'),
          );
        }
        navItems.add(
          const BottomNavigationBarItem(
              icon: Icon(Icons.category_rounded), label: 'Add a Product !'),
        );
        return navItems;
      }
    }