Is there a workaround to allow passing through tap/gesture events to widgets below a ModalRoute?

Viewed 60

I am trying to implement a nested router in my Flutter app using auto_router, however I have a map widget (flutter_map) that appears below the nested router which I would like to still be able to receive gestures. These gestures are by default blocked by ModalRoute, and by extension PageRoute.

Stack(
  children: const [
    MapWidget(), // need gestures to also get passed through to this
    AutoRouter(), // renders child routes (PageRoute) which contain elements that should be clickable
  ],
),

Based on this GitHub issue, it appears that there's no way to disable the gesture-blocking behavior of ModalRoute. Are there any good workarounds to allow the scenario above to function as intended, with the child routes being able to receive gestures without blocking them from propagating to the map below?

1 Answers

At @pskink's advice, I ended up creating a custom route by extending TransitionRoute directly. While there is a pretty significant amount of logic in ModalRoute, most of this logic is not necessary for my particular use case.

This was the solution I came up with, a class that extends TransitionRoute and implements a transitionBuilder and pageBuilder which behave similarly to those in ModalRoute.

class TranslucentRoute<T> extends TransitionRoute<T> {
  final bool _opaque;
  final Duration _transitionDuration;
  final RouteTransitionsBuilder _transitionBuilder;
  final RoutePageBuilder _pageBuilder;

  TranslucentRoute({
    opaque = true,
    transitionDuration = const Duration(milliseconds: 300),
    required RouteTransitionsBuilder transitionBuilder,
    required RoutePageBuilder pageBuilder,
    RouteSettings? settings,
  }):
    _opaque = opaque,
    _transitionDuration = transitionDuration,
    _transitionBuilder = transitionBuilder,
    _pageBuilder = pageBuilder,
    super(settings: settings);

  @override
  Iterable<OverlayEntry> createOverlayEntries() {
    return <OverlayEntry>[
      OverlayEntry(
        builder: (context) => _transitionBuilder(
          context,
          animation!,
          secondaryAnimation!,
          _pageBuilder(
            context,
            animation!,
            secondaryAnimation!,
          ),
        ),
      ),
    ];
  }

  @override
  bool get opaque => _opaque;

  @override
  Duration get transitionDuration => _transitionDuration;
}
Related