avoid_unnecessary_gesture_detector
v0.4.0 Warning Fix Widget Best Practices
Flags a GestureDetector with no argument whose name starts with on.
A handler-less GestureDetector still takes part in hit testing, so it can quietly swallow touches meant for something underneath — especially with behavior: HitTestBehavior.opaque. Either the handler was deleted and the wrapper left behind, or the handler was never wired up and the tap has been dead since it shipped.
This rule is in the recommended preset, so it is on with preset: recommended and every preset above it. No configuration.
See also: GestureDetector
The usual origin: the callback moved somewhere else and the wrapper stayed:
class ProductTile extends StatelessWidget { const ProductTile({super.key});
@override Widget build(BuildContext context) { return GestureDetector( behavior: HitTestBehavior.opaque, child: const Text('Product'), ); }}Either wire the handler back up:
class ProductTile extends StatelessWidget { const ProductTile({required this.onOpen, super.key});
final VoidCallback onOpen;
@override Widget build(BuildContext context) { return GestureDetector( behavior: HitTestBehavior.opaque, onTap: onOpen, child: const Text('Product'), ); }}Or drop the wrapper — the quick fix does this, replacing the GestureDetector with its child:
@overrideWidget build(BuildContext context) => const Text('Product');Non-handler arguments do not count
Section titled “Non-handler arguments do not count”behavior, excludeFromSemantics, dragStartBehavior and friends configure the detector; they do not give it anything to do. Only an on* argument counts:
// Still reported — no on* argumentGestureDetector( behavior: HitTestBehavior.translucent, excludeFromSemantics: true, child: const Text('Nothing happens'),);Prefer InkWell when the tap is a Material one
Section titled “Prefer InkWell when the tap is a Material one”If you are adding a handler back to get a tap, InkWell gives you the ripple as well:
InkWell( onTap: onOpen, child: const Text('Product'),);Known limitations
Section titled “Known limitations”Any argument whose name starts with on satisfies the rule, so onSomethingElse: null — an explicitly null handler — keeps it quiet. The rule reads the argument name, not the value.
RawGestureDetector and Listener are not checked.
Turning this rule off
Section titled “Turning this rule off”rules: avoid_unnecessary_gesture_detector: falseTo keep the rule on but skip certain paths, use per-rule exclude.
Related rules
Section titled “Related rules”always_pass_global_key— Don’t create a GlobalKey inside build.avoid_conditional_hooks— Never call hooks inside conditionals, loops, or ternaries.avoid_deep_widget_nesting— Keep a widget tree within a nesting budget.avoid_flexible_outside_flex— Only use Flexible and Expanded as direct children of Row, Column, or Flex.