简体   繁体   中英

Flutter GestureDetector with CustomPaint not working

I am trying to create some custom widgets using CustomPaint and GestureDetector. However, I am unable to properly interact with the drawn shapes using the GestureDetector. I can detect onTap for only one shape if the container is screen width and height, or none at all.

Please note that I have tried all HitTestBehavior types.

Here is the code whilst it's not detecting anything onTap:

class CanvasObject {
  Color color = Colors.green[800];
  double strokeWidth = 10.0;
  PaintingStyle style = PaintingStyle.stroke;
}

class CanvasNodeObject extends CanvasObject {
  double x;
  double y;
  double radius = 20;
  PaintingStyle style = PaintingStyle.fill;
  CanvasNodeObject({@required this.x, @required this.y});
}
class CanvasNodePainter extends CustomPainter {
  CanvasNodeObject node;
  CanvasNodePainter({this.node});

  @override
  void paint(Canvas canvas, Size size) {
    Path path;
    Paint nodePaint = Paint()
      ..color = node.color
      ..style = node.style;

    path = Path();
    path.moveTo(0, 0);
    path.addOval(
        Rect.fromCircle(center: Offset(0, 0), radius: node.radius));
    canvas.drawPath(path, nodePaint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}

class TestLineDrawing extends StatefulWidget {
  CanvasNodeObject startNode;
  CanvasNodeObject endNode;
  CanvasLineObject line;
  TestLineDrawing({List<double> x, List<double> y})
      : assert(x.length == 2),
        assert(y.length == 2) {
    startNode = CanvasNodeObject(x: x[0], y: y[0]);
    endNode = CanvasNodeObject(x: x[1], y: y[1]);
    line = CanvasLineObject(x: x, y: y);
  }

  @override
  _TestLineDrawingState createState() => _TestLineDrawingState();
}

class _TestLineDrawingState extends State<TestLineDrawing> {
  List<Widget> line() {
    return [
      Positioned(
        top: widget.endNode.x,
        left: widget.endNode.y,
        child:
      GestureDetector(
        behavior: HitTestBehavior.opaque,
        child:
        Container(
          height: widget.endNode.radius,
            width: widget.endNode.radius,
            child: CustomPaint(painter: CanvasNodePainter(node: widget.endNode))),
        onTap: () {
          setState(() {
            Random random = Random();
            widget.endNode.color = Color.fromARGB(255, random.nextInt(255), random.nextInt(255), random.nextInt(255));
            debugPrint("EndNodeOnPress " + widget.endNode.color.toString());
          });
        },
      )),
    ];
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Stack(
      children: line(),
    ));
  }

On screen it is: 在此处输入图像描述

I resolved this issue by doing the following:

  1. Adding all paths to a top level path called path using Path::addPath
  2. Overriding hitTest and using Path::contains
  @override
  bool hitTest(Offset position) {
    bool hit = path.contains(position);
    return hit;
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM