How to wrap a PopupMenuItem in a seperate file?

Viewed 17

I would like to wrap a PopupMenuItem in a seperate file, because I am going to need a lot of them. I fail to do so because the itemBuilder in the PopupMenuButton excpects something I cannot fulfill.

This i where I want to use the wrapped item:

PopupMenuButton<String>(
    itemBuilder: (context) => [MyWrappedMenuItem(title: 'title')],
)

And this is the wrapped PopupMenuItem component file:

class MyWrappedMenuItem extends StatelessWidget {
  final String title;
  final String? value;
  final IconData? icon;
  final void Function()? onTap;
  const MyWrappedMenuItem({Key? key, required this.title, this.value, this.icon, this.onTap}) : super(key: key);

  @override
  PopupMenuEntry<String> build(BuildContext context) {
    return PopupMenuItem(
      value: value,
      child: ListTile(
        onTap: onTap,
        minLeadingWidth: 1,
        contentPadding: EdgeInsets.only(left: 0),
        title: Text(title, style: Theme.of(context).textTheme.subtitle1),
        leading: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Icon(
              icon,
              size: 16,
            ),
          ],
        ),
      ),
    );
  }
}

I´ve tried playing around with some typecasting, but none of it seems to work. I get this error:

_CastError (type 'MyWrappedMenuItem' is not a subtype of type 'PopupMenuEntry' in type cast)

So what is wrong, and how do you properly wrap this item, or another flutter UI component item for that matter?

1 Answers

it expects a PopupMenuItem but by wrapping it in a StatelessWidget it's no longer that so you can't use that. The solution is to make a new function that returns it instead. So something like this:

PopupMenuEntry<String> myWrappedMenuItem (BuildContext context, {required String title, String? value, IconData? icon, void Function()? onTap}) {
  return PopupMenuItem(
    value: value,
    child: ListTile(
      onTap: onTap,
      minLeadingWidth: 1,
      contentPadding: EdgeInsets.only(left: 0),
      title: Text(title, style: Theme.of(context).textTheme.subtitle1),
      leading: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Icon(
            icon,
            size: 16,
          ),
        ],
      ),
    ),
  );
}
Related