Animated Battery Charge with Custom Painter in Flutter
Hi there, flutter enthusiast! 😀 Today, we will learn how to draw custom shapes with CustomPainter
and will also learn how to animate drawings.
Before diving into code, let’s see what the final output will look like
Custom Painter: Custom painter provides us a canvas
on which we can draw different shapes with colors and strokes. To use a Custom Painter, we need to use CustomPaint
widget. You can go read the flutter doc https://api.flutter.dev/flutter/rendering/CustomPainter-class.html to know more about them.
So let’s begin. We will create a BatteryChargePainter
first to start drawing.
class BatteryChargePainter extends CustomPainter {
BatteryChargePainter({
required this.charge,
});
final int charge;
final double batteryShellWidth = 100;
final double batteryShellHeight = 50;
final batteryShellPainter = Paint()
..style = PaintingStyle.stroke
..color = Colors.black;
@override
void paint(Canvas canvas, Size size) {
final center = Offset(size.height / 2, size.width / 2);
final shellRect = Rect.fromCenter(
center: center,
width: batteryShellWidth,
height: batteryShellHeight,
);
canvas.drawRect(shellRect, batteryShellPainter);
}
@override
bool shouldRepaint(BatteryChargePainter oldDelegate) {
return oldDelegate.charge != charge;
}
}
What we are doing here is, we created a Paint
object with style and color to draw the shell of the battery. Then, inside the paint
method, we calculated the center of the canvas and created shellRect
which contains information to draw rectangle on the canvas.
Later, we need to create remaining rectangles for charge
displaying and for positive power indicator and draw them on canvas similarly.
Animating the charge: If you notice, we are passing the charge
as parameter which will be used to draw charge rectangle. Now, the idea is to pass different charge value at some interval and to rebuild the UI.
We will use TweenAnimationBuilder
widget to animated the charge value. TweenAnimationBuilder
is a widget builder that animates a property of a widget.
The code will be as the following:
TweenAnimationBuilder(
tween: IntTween(begin: 0, end: 100),
duration: const Duration(seconds: 2),
builder: (_, charge, __) {
return CustomPaint(
size: const Size(200, 200),
painter: BatteryChargePainter(
charge: charge,
),
);
},
);
Here, TweenAnimationBuilder
rebuilds the CustomPaint widget at some interval to provide animation effect within the given Duration.
Now, we want to repeat the reversed animation once current one finishes. To do that, we need our current widget to be a stateful widget and in onEnd
callback of TweenAnimationBuilder
we call setState to trigger a recomposition.
class BatteryCharge extends StatefulWidget {
const BatteryCharge({Key? key}) : super(key: key);
@override
State<BatteryCharge> createState() => _BatteryChargeState();
}
class _BatteryChargeState extends State<BatteryCharge> {
bool _isReversed = false;
IntTween get chargeTween {
if (_isReversed) {
return IntTween(begin: 100, end: 0);
}
return IntTween(begin: 0, end: 100);
}
void repeatReversed() {
setState(() {
_isReversed = !_isReversed;
});
}
@override
Widget build(BuildContext context) {
return TweenAnimationBuilder(
tween: chargeTween,
duration: const Duration(seconds: 2),
onEnd: repeatReversed,
builder: (_, charge, __) {
return CustomPaint(
size: const Size(200, 200),
painter: BatteryChargePainter(
charge: charge,
),
);
},
);
}
}
So, that’s it ! We have successfully built a custom shape and animated that😎
Full source code is available here https://github.com/islamdidarmd/animated-battery-charge-flutter
Follow me on
Twitter: https://twitter.com/islamdidarmd