How do I get to tap on a CustomPaint path in Flutter using GestureDetect?
Solution 1
You have to override the hitTest()
method of your KeyPathPainter
class:
@override
bool hitTest(Offset position) {
// _path - is the same one we built in paint() method;
return _path.contains(position);
}
That will allow GestureDetector
to detect taps inside the path instead of the entire CustomPaint
container. Though the _path
must be closed since there's no way—at least that I know of—to test hits on curves.
Solution 2
Wrapping your paint with a gesture detector should do the work.
GestureDetector(
onTapDown: (details) {
print("${details.globalPosition.dx}");
print("${details.globalPosition.dy}");
},
),
Solution 3
I came to this from googling an issue I had. My issue was I was just wrapping the Painter in a gesture detector like:
GestureDetector(
child: CustomPaint(
painter: CustomPainter(),
),
onTapDown: _handleTapDown,
);
Where the solution was I needed to have a Container
with a color, wrapping the Custom Painter, like so:
return GestureDetector(
child: Container(
width: 300,
height: 300,
color: Colors.white,
child: CustomPaint(
painter: CustomPainter(),
),
),
onTapDown: _handleTapDown,
);
graciax452
Updated on November 21, 2022Comments
-
graciax452 over 1 year
I'm very new to flutter and am trying to figure out how to get a gesture detected on a CustomPaint path. I can click on a host of other things but not on paths for some reason... How do I get this to work? My code thus far is below.
import 'package:flutter/material.dart'; void main() => runApp(MbiraShapes()); class MbiraShapes extends StatefulWidget { @override _MbiraShapesState createState() => _MbiraShapesState(); } class _MbiraShapesState extends State<MbiraShapes>{ @override Widget build(BuildContext context) { return MaterialApp( title: 'Mbira Shapes', home: PathExample()); } } class PathExample extends StatelessWidget { @override Widget build(BuildContext context) { return CustomPaint( painter: KeyPathPainter(), ); } } class KeyPathPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { Paint lineDrawer = Paint() ..color = Colors.blue ..strokeWidth = 8.0; Path path = Path() // Moves to starting point ..moveTo(50, 50) //draw lines passing through xc, yc to end at x,y ..quadraticBezierTo(77, 370, 50, 750) ..quadraticBezierTo(100, 775, 150, 750) ..quadraticBezierTo(110, 440, 75, 50); //close shape from last point path.close(); canvas.drawPath(path, lineDrawer); Path path2 = Path() // Moves to starting point ..moveTo(250, 50) //draw lines passing through xc, yc to end at x,y ..quadraticBezierTo(280, 350, 270, 675) ..quadraticBezierTo(290, 750, 350, 750) ..quadraticBezierTo(365, 710, 345, 600) ..quadraticBezierTo(320, 450, 270, 50); //close shape from last point path2.close(); canvas.drawPath(path2, lineDrawer); } @override bool shouldRepaint(CustomPainter oldDelegate) => true; }
I tried the snippet below with GestureDetector but it does not work. I tried a Listener but get no response for onPointerDown, only for onPointerMove, but I need a tap action, not a move action.
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("widget.title)"), ), body: Center( child: GestureDetector( child: CustomPaint( painter: KeyPathPainter(), child: Container()), onTap: () { print("tapped the key"); }, ), ), ); }
I just want to tap a key and get a response, it will be a sound in the end but for now, I'm just trying to figure out how to get the onTap to work.