'In Flutter can I make the children of a DropdownButton a widget other than DropdownMenuItem

I have a Flutter web app, which includes a web view on some pages.

I'm using the PointerInterceptor to prevent my web view from absorbing click events.

This works well, but I have a situation now where I've got a DropdownButton and clicking it creates a bunch of DropdownMenuItems - I want to wrap those items in the same PointerInterceptor, like this :

DropdownButton<dynamic>(
                items: myItems.map((e) => PointerInterceptor( child: DropdownMenuItem(
                  value: e,
                  child: Text(e.name),
                ))).toList(),

The problem is that this results in the following error :

The argument type 'List' can't be assigned to the parameter type 'List<DropdownMenuItem>?'.

But I have put my DropdownButton in the app bar, and the DropdownMenuItems are injected into the Widget tree directly under the MaterialApp widget, so there isn't a higher level widget I can wrap.

How can I use the PointerInterceptor widget when the DropdownButton expects items to be DropdownMenuItems?



Solution 1:[1]

I was able to achieve this by making another class that wrapped the DropdownMenuItems , and then use that as the items in the DropdownButton in its place.
(ie. replace DropdownMenuItems with PointerInterceptedDropdownMenuItem)

Here is the definition of my wrapper class :

class PointerInterceptedDropdownMenuItem<T> extends DropdownMenuItem {

  final VoidCallback? onTap;
  final T? value;
  final bool enabled;

  const PointerInterceptedDropdownMenuItem({
    Key? key,
    this.onTap,
    this.value,
    this.enabled = true,
    AlignmentGeometry alignment = AlignmentDirectional.centerStart,
    required Widget child,
  }) : super(key: key, alignment:alignment, child: child);

  @override Widget build(BuildContext context) {
    return PointerInterceptor( child: super.build(context) );
  }
}

NB: This is a good, tidy solution for the part of the question asking about having the children of a DropdownButton be other than a DropdownMenuItem,
but it is not a good solution for the specific part of wrapping the items in the PointerInterceptor class, and that is because having that many PointerInceptors (I have a long list) has a bad impact on performance, therefore the solution for that part will be to move the PointerInterceptor to the top level of the scaffold and then making it conditional, and updating some state (reflecting the dropdown list being open)to say if the PointerInterceptor should cover the whole screen or not.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Turkey