Created
March 12, 2025 10:51
-
-
Save EsinShadrach/f3aef8e433106d8d8122a57605f391f7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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