Created
October 26, 2021 14:08
-
-
Save bluemix/4c932e8c4a1cd6f497a4353d9e536f57 to your computer and use it in GitHub Desktop.
Animated Counter Text for Flutter
This file contains 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 AnimatedCount extends ImplicitlyAnimatedWidget { | |
AnimatedCount({ | |
Key? key, | |
required this.count, | |
Duration duration = const Duration(milliseconds: 600), | |
Curve curve = Curves.fastOutSlowIn, | |
}) : super(duration: duration, curve: curve, key: key); | |
final num count; | |
@override | |
ImplicitlyAnimatedWidgetState<ImplicitlyAnimatedWidget> createState() { | |
return _AnimatedCountState(); | |
} | |
} | |
class _AnimatedCountState extends AnimatedWidgetBaseState<AnimatedCount> { | |
IntTween _intCount = IntTween(begin: 0, end: 1); | |
Tween<double> _doubleCount = Tween<double>(); | |
@override | |
Widget build(BuildContext context) { | |
return widget.count is int | |
? Text(_intCount.evaluate(animation).toString()) | |
: Text(_doubleCount.evaluate(animation).toStringAsFixed(1)); | |
} | |
@override | |
void forEachTween(TweenVisitor<dynamic> visitor) { | |
if (widget.count is int) { | |
_intCount = visitor( | |
_intCount, | |
widget.count, | |
(dynamic value) => IntTween(begin: value), | |
) as IntTween; | |
} else { | |
_doubleCount = visitor( | |
_doubleCount, | |
widget.count, | |
(dynamic value) => Tween<double>(begin: value), | |
) as Tween<double>; | |
} | |
} | |
} |
Another issue I have faced that it not animating in first render. to fix that I have added the initState
:
import 'package:flutter/material.dart';
class AnimatedCount extends ImplicitlyAnimatedWidget {
const AnimatedCount({
Key? key,
required this.count,
this.style,
Duration duration = const Duration(milliseconds: 600),
Curve curve = Curves.fastOutSlowIn,
this.prefix = '',
this.suffix = '',
}) : super(duration: duration, curve: curve, key: key);
final num count;
final String prefix;
final String suffix;
final TextStyle? style;
@override
ImplicitlyAnimatedWidgetState<ImplicitlyAnimatedWidget> createState() {
return _AnimatedCountState();
}
}
class _AnimatedCountState extends AnimatedWidgetBaseState<AnimatedCount> {
IntTween _intCount = IntTween(begin: 0, end: 1);
Tween<double> _doubleCount = Tween<double>(begin: 0, end: 1);
@override
void initState() {
super.initState();
if (widget.count is int) {
_intCount = IntTween(begin: 0, end: widget.count.toInt());
} else {
_doubleCount = Tween<double>(begin: 0, end: widget.count.toDouble());
}
controller.forward();
}
@override
Widget build(BuildContext context) {
final String text;
if (widget.count is int) {
final countStr = _intCount.evaluate(animation).toString();
text = '${widget.prefix}$countStr${widget.suffix}';
} else {
final countStr = _doubleCount.evaluate(animation).toStringAsFixed(1);
text = '${widget.prefix}$countStr${widget.suffix}';
}
return Text(text, style: widget.style);
}
@override
void forEachTween(TweenVisitor<dynamic> visitor) {
if (widget.count is int) {
_intCount = visitor(
_intCount,
widget.count,
(dynamic value) => IntTween(begin: value),
) as IntTween;
} else {
_doubleCount = visitor(
_doubleCount,
widget.count,
(dynamic value) => Tween<double>(begin: value),
) as Tween<double>;
}
}
}
Extra: added suffix and prefix arguments.
Another issue I have faced that it not animating in first render. to fix that I have added the
initState
:import 'package:flutter/material.dart'; class AnimatedCount extends ImplicitlyAnimatedWidget { const AnimatedCount({ Key? key, required this.count, this.style, Duration duration = const Duration(milliseconds: 600), Curve curve = Curves.fastOutSlowIn, this.prefix = '', this.suffix = '', }) : super(duration: duration, curve: curve, key: key); final num count; final String prefix; final String suffix; final TextStyle? style; @override ImplicitlyAnimatedWidgetState<ImplicitlyAnimatedWidget> createState() { return _AnimatedCountState(); } } class _AnimatedCountState extends AnimatedWidgetBaseState<AnimatedCount> { IntTween _intCount = IntTween(begin: 0, end: 1); Tween<double> _doubleCount = Tween<double>(begin: 0, end: 1); @override void initState() { super.initState(); if (widget.count is int) { _intCount = IntTween(begin: 0, end: widget.count.toInt()); } else { _doubleCount = Tween<double>(begin: 0, end: widget.count.toDouble()); } controller.forward(); } @override Widget build(BuildContext context) { final String text; if (widget.count is int) { final countStr = _intCount.evaluate(animation).toString(); text = '${widget.prefix}$countStr${widget.suffix}'; } else { final countStr = _doubleCount.evaluate(animation).toStringAsFixed(1); text = '${widget.prefix}$countStr${widget.suffix}'; } return Text(text, style: widget.style); } @override void forEachTween(TweenVisitor<dynamic> visitor) { if (widget.count is int) { _intCount = visitor( _intCount, widget.count, (dynamic value) => IntTween(begin: value), ) as IntTween; } else { _doubleCount = visitor( _doubleCount, widget.count, (dynamic value) => Tween<double>(begin: value), ) as Tween<double>; } } }Extra: added suffix and prefix arguments.
This works for me, thanks 👍
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is so cool