skip to Main Content

my app isn’t working as intended, and as far as I can guess, I’m doing it correctly. I have print statements everywhere, and the points length returns 0 at first in the console and then doesnt print again. The "line drawn" statement isn’t even being triggered, the pan print statements are working fine, I dont know what part of my code is off so that the for loop isnt being triggered.

void main() async {

  //ensure flutter widgets are binding
  WidgetsFlutterBinding.ensureInitialized();

//firebase

  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

// end firebase


  runApp(MyApp());
}
class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<Offset> points = [];

  void handlePanUpdate(DragUpdateDetails details) {
    print("handled Pan Update");
    setState(() {
      points.add(details.localPosition);
    });
  }

  void handlePanEnd(DragEndDetails details) {
    print("handled Drag End");
    setState(() {
      points.clear();
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Container(
        color: Colors.blueGrey[50], // set the background color of the container
        child: GestureDetector(
          onPanUpdate: handlePanUpdate,
          onPanEnd: handlePanEnd,
          child: CustomPaint(
            painter: PaintField(points),
            size: Size.infinite,
          ),
        ),
      ),
    );
  }
}


class PaintField extends CustomPainter {
  List<Offset> points;

  PaintField(this.points);

  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()
      ..color = Colors.black
      ..strokeCap = StrokeCap.round
      ..strokeWidth = 5.0;

    print("Points length: ${points.length}");

    for (int i = 1; i < points.length; i++) {
      canvas.drawLine(points[i - 1], points[i], paint);
      print("Line drawn!");
    }
  }

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

2

Answers


  1. The CustomPaint doesn’t repaint because your oldDelegate.points equals points (in shouldRepaint; you can return true there as a test to see it working). You are comparing those lists by equality, which checks the references. And because you still pass the same list that you initialized in _MyAppState, the reference points to the same object.

    Instead of doing just .add() in your setStates, you may assign a new, updated list to the field, so that the reference changes, like so:

        setState(() {
          points = [...points, details.localPosition];
          // or this way, whichever you like more:
          points = List.of(points)..add(details.localPosition);
        });
    

    …and the same with clearing the list. This is why immutability is such an important topic in Flutter 🙂

    Login or Signup to reply.
  2. As Albert described, the is issue coming because of list equality. Also I would suggest you can take advantage of CustomPainter super constructor with ValueNotifier, NO need to call setState.

     ValueNotifier<List<Offset>> points = ValueNotifier<List<Offset>>([]);
    
      void handlePanUpdate(DragUpdateDetails details) {
        print("handled Pan Update");
    
        RenderBox object = context.findRenderObject() as RenderBox;
        Offset _localPosition = object.globalToLocal(details.globalPosition);
        points.value = [...points.value, _localPosition];
      }
    
      void handlePanEnd(DragEndDetails details) {
        points.value = [];
      }
    
    class PaintField extends CustomPainter {
      final ValueNotifier<List<Offset>> points;
    
      PaintField(this.points) : super(repaint: points);
    
      @override
      void paint(Canvas canvas, Size size) {
        Paint paint = Paint()
          ..color = Colors.black
          ..strokeCap = StrokeCap.round
          ..strokeWidth = 25.0;
    
        for (int i = 1; i < points.value.length; i++) {
          canvas.drawLine(points.value[i - 1], points.value[i], paint);
        }
      }
    
      @override
      bool shouldRepaint(PaintField oldDelegate) {
        return oldDelegate.points != points;
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search