Animated Battery Charge with Custom Painter in Flutter

Md Didarul
3 min readJan 15, 2023

--

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😎

--

--

Md Didarul

I am a Mobile Software Engineer. love to build cool things with Flutter and I have prior experience in Android App Development with Kotlin and Java