Migration to Flutter Guide
Discover our battle-tested 21-step framework for a smooth and successful migration to Flutter!
Home
Glossary

GestureDetector in Flutter

What is GestureDetector in Flutter?

GestureDetector is a Flutter widget that detects and responds to touch gestures – taps, double taps, long presses, drags, and scales – by wrapping a child widget and exposing gesture callbacks.

It adds no visual feedback of its own: no ripple, no highlight, nothing. For that, Material apps typically reach for InkWell instead, which wraps the same gesture-recognition machinery with a Material ink response.

Key facts at a glance

  • GestureDetector in Flutter is part of the core widgets library and works with or without Material.
  • It recognizes taps, double taps, long presses, pan, drag, and scale gestures through named callbacks.
  • It provides no visual feedback – no ripple, no highlight, no color change.
  • Its behavior property controls hit testing, and defaults to HitTestBehavior.deferToChild when it has a child, or HitTestBehavior.translucent when it doesn't.
  • It also listens for accessibility events and maps them to its gesture callbacks; set excludeFromSemantics to true to exclude those gestures from the semantics tree.
  • When multiple GestureDetectors compete for the same pointer event, Flutter resolves the conflict through the gesture arena, so only one recognizer typically wins.

How do I detect a tap in Flutter?

Wrap any widget in GestureDetector and provide an onTap callback.

import 'package:flutter/material.dart';

class TapCounter extends StatefulWidget {
  const TapCounter({super.key});

  @override
  State<TapCounter> createState() => _TapCounterState();
}

class _TapCounterState extends State<TapCounter> {
  int _count = 0;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => setState(() => _count++),
      child: Container(
        color: Colors.blue.shade100,
        padding: const EdgeInsets.all(16),
        child: Text('Tapped $_count times'),
      ),
    );
  }
}

Nothing here changes color or shows feedback on tap – that's expected. If the design needs a visible response, wrap the child in InkWell instead, or add your own state-driven styling.

Why is my GestureDetector not working in Flutter?

The most common cause is behavior defaulting to HitTestBehavior.deferToChild: the GestureDetector only receives pointer events where its child is hit, so tapping padding or empty space around a child can do nothing.

GestureDetector(
  behavior: HitTestBehavior.opaque,
  onTap: () {},
  child: Padding(
    padding: const EdgeInsets.all(24),
    child: const Text('Tap anywhere in this padded area'),
  ),
),

Setting behavior: HitTestBehavior.opaque makes the entire GestureDetector bounds participate in hit testing, including the padding around the text.

Note: HitTestBehavior.opaque does not make the GestureDetector larger; it makes its existing bounds hit-testable.

GestureDetector vs. InkWell

GestureDetectorInkWell
Visual feedback
NoneRipple and highlight
Requires Material ancestor
NoYes
Gesture range
Tap, double tap, long press, secondary press, drag, pan, scale, force press, and moreTap, double tap, long press, secondary press, and more
Typical use
Custom or Cupertino interactionsMaterial surfaces and tappable areas
Underlying mechanism
GestureRecognizersBuilt on InkResponse, which uses a GestureDetector

Verdict: use InkWell for tappable Material surfaces that should provide ink/ripple feedback; use GestureDetector for custom gestures, non-Material UI, or interactions that InkWell does not cover.

Best practices

  1. Set behavior explicitly when the hit-test area matters – deferToChild (the default) only considers the GestureDetector hit when its child is hit; opaque makes the entire bounds participate in hit testing; translucent also allows hit testing of widgets visually behind it.
  2. Add your own visual feedbackGestureDetector alone gives users no confirmation that a tap registered.
  3. Prefer InkWell inside Material apps when you want Material ink/ripple feedback; use GestureDetector when you need gestures such as pan or scale that InkWell does not provide.
  4. Set excludeFromSemantics: true only when another widget already provides the appropriate semantics – otherwise the gestures handled by the GestureDetector are removed from the semantics tree.
  5. Avoid nesting two GestureDetector widgets when you expect both to respond to the same gesture – competing gesture recognizers are resolved through Flutter's gesture arena, so only one typically wins.
  6. Use onDoubleTap only when double-tap interaction is actually needed. When both onTap and onDoubleTap are provided, Flutter delays onTap while it determines whether a second tap occurs, which can make single taps feel less responsive.

Common mistakes

  • Wrapping padding-heavy children and expecting the padding to be tappable. With the default deferToChild behavior, only the child's own painted area registers hits.
  • Using GestureDetector for a standard button-like action in a Material app. This misses the built-in visual feedback, disabled state, and button semantics provided by a real button widget; use InkWell when you need Material ink feedback.
  • Assuming nested GestureDetector widgets both fire on the same tap. Competing gesture recognizers are resolved through the gesture arena, so only one typically wins and invokes its callback. Hit-testing issues caused by behavior or IgnorePointer can prevent a detector from entering the competition in the first place.
  • Adding a Material ancestor unnecessarily. GestureDetector belongs to Flutter's core widgets library and does not require a Material ancestor; InkWell, by contrast, relies on a Material ancestor for its ink effects.

Learn more

Design system Flutter

Building a Design System in a Large Flutter App

Flutter is known for its seamless UI/UX features and robust design elements. It allowed us to deliver a unique customer experience in the “CA24 Mobile” banking app. This article shares some of the learnings and pain points behind implementing it in this large project.

Complex Animations in Flutter

Complex Animations in Flutter

Flutter ships with plenty of high-quality widgets, layouts, and themes that developers can use to speed up the whole creation process. A great example of custom widgets made in Flutter is the Placement Wheel developed for one of our clients. See how to do it.