Making interactive drawings on a canvas in Flutter often involves using CustomPaint. But how do you know where on your drawing the user tapped? That's where GestureDetector comes in handy.
Combining CustomPaint and GestureDetector
You wrap your CustomPaint widget inside a GestureDetector. The GestureDetector handles tap events on the whole area its child covers.
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => print("do what you want"), // This will fire when a tap is detected
child: CustomPaint(
size: Size.infinite,
painter: WorldPainter(),
),
);
}
Controlling Tap Detection with hitTest
Sometimes, you only want to react to taps that are close to a specific item you've drawn, like a circle or a character. CustomPainter has a special method called hitTest for this exact purpose.
How hitTest Works
The GestureDetector passes the tap position (an Offset) to the hitTest method of your CustomPainter. If hitTest returns true, the GestureDetector considers it a "hit" on the painter, and its tap callbacks (onTap, onPanDown, etc.) will fire. If hitTest returns false, the tap is ignored by this GestureDetector.
Implementing Radius-Based Detection
Inside your hitTest method, you can write logic to check if the tap position (position) is within a certain distance of the location you care about (this.location).
class WorldPainter extends CustomPainter {
// ... other painter code ...
bool hitTest(Offset position) {
var distance = position.distanceTo(this.location); // Calculate distance from tap to target
return distance < detectionRadius; // Return true if within the radius
}
// ... rest of the painter class ...
}
Example Calculation
This snippet calculates the distance between the tap point (position) and your defined location. It then checks if this distance is less than your detectionRadius. If it is, the method returns true, signalling to the GestureDetector that the tap occurred where you wanted it to.
By implementing hitTest in your CustomPainter, you gain fine-grained control over when and where taps on your canvas trigger reactions.