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
The
CustomPaint
doesn’t repaint because youroldDelegate.points
equalspoints
(inshouldRepaint
; you can returntrue
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 yoursetState
s, you may assign a new, updated list to the field, so that the reference changes, like so:…and the same with clearing the list. This is why immutability is such an important topic in Flutter 🙂
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.