Short answer
Hit testing searches down the tree to gather the RenderObjects located under the touch point, then the GestureRecognizers compete in an arena (GestureArena) to determine the winner based on the user's movement or the dragging of other gestures.
Explanation
When the screen is touched, the engine sends a PointerDownEvent and starts calling hitTest() downward from the RenderView to the deepest leaves of the tree, and each element that accepts touch registers itself in the HitTestResult. After that, the attached GestureRecognizers (such as TapGestureRecognizer and HorizontalDragGestureRecognizer) join the GestureArena. The arena forwards the movement events, and if the user drags horizontally past the drag threshold, the drag declares acceptance of the gesture (acceptGesture), winning the arena, and the tap is rejected immediately. If the user lifts the finger before any competitor declares victory, the arena performs a sweep that gives the win to the first registered member (usually the tap).
Code example
// Customize hit testing behavior through HitTestBehavior:
Listener(
behavior: HitTestBehavior.opaque, // Captures touch even in transparent empty areas
onPointerDown: (event) => print('Touch at ${event.position}'),
child: Container(height: 100),
)Common mistakes
- Not setting HitTestBehavior.opaque on containers with transparent backgrounds, so touch events pass to the elements behind and the GestureDetector is ignored.