Search code examples
flutterlistdarticonspopupmenubutton

defining and accessing a list to build the content of a popup menu button including icons


In _HomePageState I have a PopupMenuButton defined as

          PopupMenuButton(
            icon: Icon(Icons.more_vert),
            itemBuilder: (BuildContext context) {
              return <PopupMenuItem>[
                PopupMenuItem(
                  onTap: () {
                    BlocProvider.of<BlocAuth>(context)
                        .add(Setting8EventAuth());
                  },
                  child: ListTile(
                    leading: Icon(Icons.settings),
                    title: Text('Settings'),
                  ),
                ),
                PopupMenuItem(
                  onTap: () {
                    BlocProvider.of<BlocAuth>(context)
                        .add(SignOut8EventAuth());
                  },
                  child: ListTile(
                    leading: Icon(Icons.settings),
                    title: Text('Logout'),
                  ),
                ),
              ];
            },

I would like to set a list of items related to the content PopupMenuButton and call that list rather than multiplying the same code for each item.

Still in _HomePageState (even though eventually I would like to move it elsewhere), based on

Flutter - PopupMenuButton - add an item manually after adding items from a list I have defined

  List<PopupMenuContent> items = [
    PopupMenuContent(
      name: 'Profile',
      iconFile: 'person.jpg',
      event: 'Profile8EventAuth()',
    ),
    PopupMenuContent(
      name: 'Settings',
      iconFile: 'settings.jpg',
      event: 'Settings8EventAuth()',
    ),
    PopupMenuContent(
      name: 'Logout',
      iconFile: 'logout.jpg',
      event: 'SignOut8EventAuth()',
    ),
  ];

which I hoped to call in PopupMenuButton with something close to

          PopupMenuButton(
            icon: Icon(Icons.more_vert),
            itemBuilder: (BuildContext context) {
              return items.map((item) {
                return PopupMenuItem(
                  child: ListTile(
                    leading: Icon(Icons.${item.iconFile}),
                    title: Text(item.name),
                  ),
                  onTap: () {
                    BlocProvider.of<BlocAuth>(context).add(item.event as AbstEventAuth);
                  },
                );
              }).toList();
            },
          )

I'm not sure casting in BlocProvider will work, but the first issue is with error message I get is related to leading: Icon(Icons.${item.iconFile}),. Even though not that neat, I could set String itemIF = item.iconFile; between the 2 returns, but then I cannot insert it in leading: Icon(Icons.xxxAboutHerexxxx),.

Any suggestion ?


Solution

  • use IconData for your icon in items list to define the icon not the string. Same goes for your function.

    Redefine the PopupMenuContent class

    class PopupMenuContent {
      final String name;
      final IconData iconData;
      final Function event;
    
      PopupMenuContent({required this.name, required this.iconData, required this.event});
    }
    

    Now make list accordingly

     List<PopupMenuContent> items = [
        PopupMenuContent(
          name: 'Profile',
          iconData: Icons.person,
          event: () {
            BlocProvider.of<BlocAuth>(context).add(Profile8EventAuth());
          },
        ),
        PopupMenuContent(
          name: 'Settings',
          iconData: Icons.settings,
          event: () {
            BlocProvider.of<BlocAuth>(context).add(Settings8EventAuth());
          },
        ),
        PopupMenuContent(
          name: 'Logout',
          iconData: Icons.logout,
          event: () {
            BlocProvider.of<BlocAuth>(context).add(SignOut8EventAuth());
          },
        ),
      ];
    

    build fn

    @override
      Widget build(BuildContext context) {
        return PopupMenuButton(
          icon: Icon(Icons.more_vert),
          itemBuilder: (BuildContext context) {
            return items.map((item) {
              return PopupMenuItem(
                child: ListTile(
                  leading: Icon(item.iconData),
                  title: Text(item.name),
                ),
                onTap: () {
                  item.event();
                },
              );
            }).toList();
          },
        );
      }