I'm trying to understand how shouldRepaint works. I found a tutorial that paints a dial around a circle button to show its value. The example had shouldRepaint always return true. Basically it just paints a partial circle around the button to show the % value. If the value is 50, the circle would go half way around.
I set shouldRepaint to always return false to see what would happen. It still painted the button circle correctly.
My theory is that it will always paint when the stateful widget is redrawn. So when the button value goes from 40% to 50%, the widget redraws and the painting is done no matter what.
So if my widget is painted anyway when the state changes, when would I use shouldRepaint?
Here is the relevant code from the tutorial:
class HomeContent extends StatefulWidget {
@override
_HomeContentState createState() => _HomeContentState();
}
class _HomeContentState extends State<HomeContent> {
int percentage;
@override
void initState() {
super.initState();
setState(() {
percentage = 0;
});
}
@override
Widget build(BuildContext context) {
return new Center(
child: new Container(
height: 200.0,
width: 200.0,
child: new CustomPaint(
foregroundPainter: new MyPainter(
lineColor: Colors.amber,
completeColor: Colors.blueAccent,
completePercent: percentage,
width: 8.0),
child: new Padding(
padding: const EdgeInsets.all(8.0),
child: new RaisedButton(
color: Colors.purple,
splashColor: Colors.blueAccent,
shape: new CircleBorder(),
child: new Text("$percentage%"),
onPressed: () {
setState(() {
percentage += 10;
if (percentage > 100) {
percentage = 0;
}
});
}),
),
),
),
);
}
}
class MyPainter extends CustomPainter {
Color lineColor;
Color completeColor;
int completePercent;
double width;
MyPainter(
{this.lineColor, this.completeColor, this.completePercent, this.width});
@override
void paint(Canvas canvas, Size size) {
Paint line = new Paint()
..color = lineColor
..strokeCap = StrokeCap.round
..style = PaintingStyle.stroke
..strokeWidth = width;
Paint complete = new Paint()
..color = completeColor
..strokeCap = StrokeCap.round
..style = PaintingStyle.stroke
..strokeWidth = width;
Offset center = new Offset(size.width / 2, size.height / 2);
double radius = min(size.width / 2, size.height / 2);
canvas.drawCircle(center, radius, line);
double arcAngle = 2 * pi * (completePercent / 100.0);
if (arcAngle >= 2 * pi) arcAngle = 2 * pi - 0.001; // cannot draw a complete circle arc
canvas.drawArc(new Rect.fromCircle(center: center, radius: radius), -pi / 2,
arcAngle, false, complete);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
Custom Painter is : A widget that provides a canvas on which to draw during the paint phase. :To paint in Flutter you can use the CustomPaint widget which basically takes size of its parent if not given the child . The CustomPainter subclass overrides two methods: paint() and shouldRepaint() .
From Docs, shouldRepaint()
:
If the new instance represents different information than the old instance, then the method should return true, otherwise it should return false
Also,
It's possible that the paint method will get called even if shouldRepaint returns false (e.g. if an ancestor or descendant needed to be repainted). It's also possible that the paint method will get called without shouldRepaint being called at all (e.g. if the box changes size)
So, a good way would be to use
@override
bool shouldRepaint(MyPainter oldDelegate) =>
oldDelegate.completePercent != completePercent;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With