Flutter
Challenge 4
Build a chart animation with CustomPainter and AnimationController.
Challenge 4 - Graphic animation
In this challenge you will animate a circle's radius with CustomPainter and AnimationController. As the controller goes from 0.0 to 1.0, a Tween(0, 50) grows the radius and you draw it with canvas.drawCircle.
class CirclePainter extends CustomPainter {
final AnimationController ctrl;
CirclePainter(this.ctrl) : super(repaint: ctrl);
@override
void paint(Canvas canvas, Size size) {
final r = Tween(begin: 0.0, end: 50.0).transform(ctrl.value);
canvas.drawCircle(Offset(50, 50), r, Paint());
}
@override
bool shouldRepaint(covariant CirclePainter old) => false;
}
Exercise Define CirclePainter
First define _EmptyVsync implementing TickerProvider. Define CirclePainter extending CustomPainter: take an AnimationController parameter named ctrl and call super(repaint: ctrl) in the constructor. In paint, compute r with Tween(begin: 0.0, end: 50.0).transform(ctrl.value) and draw canvas.drawCircle(const Offset(50, 50), r, Paint()). shouldRepaint returns false. In main, create ctrl, take a CirclePainter instance, print runtimeType.
Show example solution
import 'package:flutter/material.dart';
class _EmptyVsync implements TickerProvider {
@override
Ticker createTicker(TickerCallback onTick) => Ticker(onTick);
}
class CirclePainter extends CustomPainter {
final AnimationController ctrl;
CirclePainter(this.ctrl) : super(repaint: ctrl);
@override
void paint(Canvas canvas, Size size) {
final r = Tween(begin: 0.0, end: 50.0).transform(ctrl.value);
canvas.drawCircle(const Offset(50, 50), r, Paint());
}
@override
bool shouldRepaint(covariant CirclePainter old) => false;
}
void main() {
final ctrl = AnimationController(
vsync: _EmptyVsync(),
duration: Duration(seconds: 1),
);
final painter = CirclePainter(ctrl);
print(painter.runtimeType);
ctrl.dispose();
}
Exercise Compute radius with Tween
Define _EmptyVsync implementing TickerProvider. In main, create an AnimationController named ctrl (vsync: _EmptyVsync(), duration 1 second). Set ctrl.value = 0.5. Compute r with Tween(begin: 0.0, end: 50.0).transform(ctrl.value) and print r. Then call ctrl.dispose().
Show example solution
import 'package:flutter/material.dart';
class _EmptyVsync implements TickerProvider {
@override
Ticker createTicker(TickerCallback onTick) => Ticker(onTick);
}
void main() {
final ctrl = AnimationController(
vsync: _EmptyVsync(),
duration: Duration(seconds: 1),
);
ctrl.value = 0.5;
final r = Tween(begin: 0.0, end: 50.0).transform(ctrl.value);
print(r);
ctrl.dispose();
}
Test yourself
-
How do we connect a CustomPainter to an animation?
- By initState
- By setState
- By super(repaint: ctrl)
- By dispose
Show answer
By super(repaint: ctrl) — The CustomPainter is given super(repaint: ctrl); whenever the controller changes, the painter repaints automatically.
-
Pass radius to drawCircle
canvas.drawCircle(Offset(50, 50), ____, Paint());
Show answer
canvas.drawCircle(Offset(50, 50), r, Paint());
-
Graphic animation matches
- CustomPainter
- Drawing class
- AnimationController
- Animation control
- Tween
- Value range
- repaint
- Repaint trigger
Next lesson: Advanced section exam