Skip to content

Instantly share code, notes, and snippets.

@EsinShadrach
Created March 12, 2025 10:51
Show Gist options
  • Select an option

  • Save EsinShadrach/f3aef8e433106d8d8122a57605f391f7 to your computer and use it in GitHub Desktop.

Select an option

Save EsinShadrach/f3aef8e433106d8d8122a57605f391f7 to your computer and use it in GitHub Desktop.
class AnimatedDigit extends StatefulWidget {
final int value;
final TextStyle? style;
const AnimatedDigit({
super.key,
required this.value,
this.style,
});
@override
State<AnimatedDigit> createState() => _AnimatedDigitState();
}
class _AnimatedDigitState extends State<AnimatedDigit>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
int _oldValue = 0;
int _newValue = 0;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 300),
);
_animation = CurvedAnimation(parent: _controller, curve: Curves.easeInOut);
_newValue = widget.value;
}
@override
void didUpdateWidget(AnimatedDigit oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.value != widget.value) {
_oldValue = oldWidget.value;
_newValue = widget.value;
_controller.forward(from: 0.0);
}
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return SizedBox(
height: 60,
child: Stack(
alignment: Alignment.center,
clipBehavior: Clip.none,
children: [
// old digit (slides out)
if (_oldValue != _newValue)
Opacity(
opacity: 1 - _animation.value,
child: Transform.translate(
offset: Offset(
0,
_newValue > _oldValue
? -_animation.value * 60
: _animation.value * 60),
child: ImageFiltered(
imageFilter:
_animation.value > 0.3 && _animation.value < 0.7
? ImageFilter.blur(sigmaX: 2, sigmaY: 2)
: ImageFilter.blur(sigmaX: 0, sigmaY: 0),
child: Text(
"$_oldValue",
textAlign: TextAlign.center,
style: widget.style,
),
),
),
),
// new digit (slides in)
Opacity(
opacity: _animation.value,
child: Transform.translate(
offset: Offset(
0,
_newValue > _oldValue
? (1 - _animation.value) * 60
: -(1 - _animation.value) * 60),
child: ImageFiltered(
imageFilter:
_animation.value > 0.3 && _animation.value < 0.7
? ImageFilter.blur(sigmaX: 2, sigmaY: 2)
: ImageFilter.blur(sigmaX: 0, sigmaY: 0),
child: Text(
"$_newValue",
textAlign: TextAlign.center,
style: widget.style,
),
),
),
),
],
),
);
},
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment