0

它适用于某些试验,然后不适用于某些试验,然后再次工作(没有任何特定模式)。我的意思是,例如,它会校正线条并仅使用第一个和最后一个点绘制完美的线条 3-4 次,然后有一次它离开用户绘制的线条。似乎points.clearorpoints.add有时有效,有时无效。我知道这听起来很傻,但我无法用合乎逻辑的方式解释它。如果有人可以查看代码并告诉我发生了什么,我将非常感激。

这是我的手势检测器:

body: GestureDetector(
        onPanDown: (DragDownDetails details) {
          setState(() {
            points.clear();
          });
        },
        onPanUpdate: (DragUpdateDetails details) {
          //when the user touch the screen and move
          setState(() {
            RenderBox box = context.findRenderObject(); //finds the scaffold
            Offset point = box.globalToLocal(details.globalPosition);
            point = point.translate(0.0, -(AppBar().preferredSize.height + 30));

            points = List.from(points)
              ..add(point); //add the points when user drag in screen
            firstPoint = points.first; //storing the first point for drawing the line
          });
        },
        onPanEnd: (DragEndDetails details) {
          setState(() {
            if (mode == "Line") {
              Offset lastPoint = points.last; //storing the last point for drawing the line
              points.clear();
              points.add(firstPoint);
              points.add(lastPoint);
              points.add(null);
            } 
          });
        },
        child: sketchArea,
      ),

这是我的 CustomPainter 类:

class Sketcher2 extends CustomPainter {
  final List<Offset> points;
  Sketcher2(this.points);

  @override
  bool shouldRepaint(Sketcher2 oldDelegate) {
    return oldDelegate.points != points;
  }

  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()
      ..color = Colors.black //seting the color of the drawing
      ..strokeCap = StrokeCap.round //the shape of a single dot (single touch)
      ..strokeWidth = 4.0; // the width of a single dot (single touch)

    for (int i = 0; i < points.length - 1; i++) {
      if (points[i] != null && points[i + 1] != null) {
        canvas.drawLine(points[i], points[i + 1], paint);
      }
    }
  }
}
4

2 回答 2

1

shouldRepaint您的 的 可能有问题Sketcher2

@override
bool shouldRepaint(Sketcher2 oldDelegate) {
  return oldDelegate.points != points;
}

操作员比较!=对象。oldDelegate.points当且仅当且points不是同一个对象时,它将返回 true 。

事实上,我很惊讶它会起作用。我试过你的源代码,但它从来没有在我这边工作过。

1. 快速解决方案

onPanEnd中,不是清除点,而是将列表重新初始化为新的[]

onPanEnd: (DragEndDetails details) {
  setState(() {
    if (mode == "Line") {
      Offset lastPoint = points.last;
      points = []; // instead of points.clear();
      points.add(firstPoint);
      points.add(lastPoint);
      points.add(null);
    } else if (mode == "FreeDraw") {
      points.add(null);
    }
  });
},

顺便说一句,您onPanUpdate通过使用带有points = List.from(points)..add(point);.

2. 进一步简化

您可以大大简化您的 GestureDetector 。

  • firstPointpoints.first,不需要为此保留一个单独的变量;
  • 你的也一样lastPoints
  • 的已经给你details了;onPanUpdatelocalPosition
  • 为什么要null在末尾添加points

你的Page变成:

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  List<Offset> points = <Offset>[];
  String mode = 'Line';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GestureDetector(
        onPanDown: (DragDownDetails details) => setState(() => points = []),
        onPanUpdate: (DragUpdateDetails details) =>
            setState(() => points = [...points, details.localPosition]),
        onPanEnd: (DragEndDetails details) => setState(() {
          if (mode == "Line") points = [points.first, points.last];
        }),
        child: SketchArea(points: points),
      ),
    );
  }
}
于 2021-03-06T17:34:11.470 回答
0

我只是改变了这部分:

points.add(firstPoint);
points.add(lastPoint);

points = List.from(points)..add(firstPoint);
points = List.from(points)..add(lastPoint);

我的问题解决了。

于 2021-03-06T19:24:58.227 回答