NumberFlow for Flutter
β¨ Beautiful, smooth animated number transitions for Flutter β¨
A Flutter port of the popular number-flow library, bringing smooth digit-by-digit animations to your Flutter apps with enhanced visual effects and polished transitions.
π¬ Live Demo
β¨ Watch NumberFlow in action: smooth digit animations, randomized directions, and seamless width transitions β¨
Demo Features Shown:
- π― Smooth digit-by-digit animations with perfect timing
- π² Randomized spin directions - each digit chooses up β¬οΈ or down β¬οΈ
- π Animated width transitions with faded edges when digit count changes
- π° Currency formatting with prefix/suffix styling
- π Percentage displays with automatic color changes
- πͺ Custom animation curves (elastic, bounce, spring, smooth)
- π Compact notation for large numbers (1.23M, 1.23B)
π Features
Feature | Description |
---|---|
π― Smooth Digit Animations | Each digit spins individually with perfect timing |
π¨ Randomized Directions | Digits spin in random directions for dynamic effects |
π Animated Width Transitions | Smooth expansion/contraction with faded edges |
β‘ High Performance | Optimized for 60fps animations |
ποΈ Highly Customizable | Control timing, curves, styling, and behavior |
π± Accessibility Support | Respects motion preferences automatically |
π§ Advanced Formatting | Prefix/suffix, decimals, grouping, compact notation |
πͺ Custom Animation Curves | Built-in curves inspired by the original library |
π Installation
Add this to your package's pubspec.yaml
file:
dependencies:
number_flow: ^1.0.0
Then run:
flutter pub get
π― Quick Start
Basic Usage
import 'package:number_flow/number_flow.dart';
NumberFlow(
value: 1234.56,
style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
)
Interactive Example
class AnimatedCounter extends StatefulWidget {
@override
_AnimatedCounterState createState() => _AnimatedCounterState();
}
class _AnimatedCounterState extends State<AnimatedCounter> {
double _value = 0;
@override
Widget build(BuildContext context) {
return Column(
children: [
NumberFlow(
value: _value,
style: TextStyle(fontSize: 48, fontWeight: FontWeight.bold),
),
ElevatedButton(
onPressed: () => setState(() => _value = Random().nextDouble() * 10000),
child: Text('Randomize'),
),
],
);
}
}
π¨ Visual Examples
π° Currency Display
Perfect for stock prices, financial data, and e-commerce:
NumberFlow(
value: stockPrice,
prefix: '\$',
suffix: ' USD',
decimalPlaces: 2,
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.w600,
color: Colors.green,
),
spinCurve: NumberFlowCurves.smoothSpin,
)
Visual Effect: $123.45 USD
β $1,234.56 USD
with smooth width expansion
π Percentage Changes
Great for statistics, progress indicators, and data visualization:
NumberFlow(
value: percentage,
suffix: '%',
showSign: true,
decimalPlaces: 2,
trend: NumberFlowTrend.auto,
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: percentage >= 0 ? Colors.green : Colors.red,
),
spinCurve: NumberFlowCurves.elastic,
)
Visual Effect: +12.34%
β -5.67%
with color change and elastic bounce
π’ Counters and Metrics
Perfect for dashboards, analytics, and real-time data:
NumberFlow(
value: counter,
trend: NumberFlowTrend.up,
style: TextStyle(
fontSize: 36,
fontWeight: FontWeight.bold,
color: Colors.blue,
),
spinDuration: Duration(milliseconds: 600),
spinCurve: NumberFlowCurves.bounce,
)
Visual Effect: Digits bounce playfully with randomized directions
π Large Numbers with Compact Notation
Ideal for follower counts, views, and big metrics:
NumberFlow(
value: 1234567890,
notation: NumberNotation.compact, // Shows as "1.23B"
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Colors.orange,
),
spinCurve: NumberFlowCurves.spring(damping: 0.6),
)
Visual Effect: 1.23M
β 1.23B
with spring physics
πͺ Animation System
Core Animation Features
π² Randomized Direction Spinning
Each digit randomly chooses to spin up β¬οΈ or down β¬οΈ, creating dynamic visual effects:
// When changing from 1234 to 5678:
// '1' might spin UP to '5'
// '2' might spin DOWN to '6'
// '3' might spin UP to '7'
// '4' might spin DOWN to '8'
π Smooth Width Transitions
Automatic width animation when digit count changes:
// Smooth expansion: 99 β 100
// Smooth contraction: 1000 β 999
// With faded edges for polished look
β±οΈ Coordinated Timing
All digits animate together with consistent, polished timing:
NumberFlow(
value: myNumber,
spinDuration: Duration(milliseconds: 600), // All digits sync
opacityDuration: Duration(milliseconds: 350), // Fade timing
transformDuration: Duration(milliseconds: 600), // Width changes
)
Custom Animation Curves
NumberFlow includes professionally designed curves:
// Available curves:
NumberFlowCurves.smoothSpin // Smooth with slight overshoot
NumberFlowCurves.elastic // Elastic bounce effect
NumberFlowCurves.bounce // Playful bounce animation
NumberFlowCurves.smoothFade // Natural opacity transitions
NumberFlowCurves.spring() // Configurable spring physics
NumberFlowCurves.anticipate // Slow start, quick acceleration
Usage Example:
NumberFlow(
value: myValue,
spinCurve: NumberFlowCurves.elastic,
opacityCurve: NumberFlowCurves.smoothFade,
transformCurve: NumberFlowCurves.smoothSpin,
)
ποΈ Comprehensive API Reference
Core Parameters
Parameter | Type | Default | Description |
---|---|---|---|
value |
num |
required | The number to display and animate |
style |
TextStyle? |
null |
Text styling for the number |
animated |
bool |
true |
Enable/disable all animations |
Text & Formatting
Parameter | Type | Default | Description |
---|---|---|---|
prefix |
String? |
null |
Text before the number (e.g., "$") |
suffix |
String? |
null |
Text after the number (e.g., " USD") |
prefixStyle |
TextStyle? |
null |
Custom styling for prefix |
suffixStyle |
TextStyle? |
null |
Custom styling for suffix |
decimalPlaces |
int? |
null |
Fixed decimal places |
useGroupSeparator |
bool |
true |
Add commas for thousands |
showSign |
bool |
false |
Show + for positive numbers |
locale |
String? |
null |
Locale for number formatting |
Number Notation
Parameter | Type | Default | Description |
---|---|---|---|
notation |
NumberNotation |
standard |
Number format style |
NumberNotation Options:
NumberNotation.standard
β1234567
NumberNotation.compact
β1.23M
NumberNotation.scientific
β1.23e6
NumberNotation.engineering
β1.235e6
Animation Control
Parameter | Type | Default | Description |
---|---|---|---|
transformDuration |
Duration |
600ms |
Width transition timing |
spinDuration |
Duration |
600ms |
Digit spin timing |
opacityDuration |
Duration |
350ms |
Fade transition timing |
transformCurve |
Curve |
easeOut |
Width animation curve |
spinCurve |
Curve |
easeOut |
Digit spin curve |
opacityCurve |
Curve |
easeOut |
Opacity animation curve |
Animation Behavior
Parameter | Type | Default | Description |
---|---|---|---|
trend |
NumberFlowTrend |
auto |
Animation direction preference |
isolate |
bool |
false |
Disable group coordination |
respectMotionPreference |
bool |
true |
Honor accessibility settings |
willChange |
bool |
false |
Hint for performance optimization |
NumberFlowTrend Options:
NumberFlowTrend.auto
β Direction based on value changeNumberFlowTrend.up
β Always animate upwardNumberFlowTrend.down
β Always animate downward
Callbacks
Parameter | Type | Default | Description |
---|---|---|---|
onAnimationStart |
VoidCallback? |
null |
Called when animation begins |
onAnimationComplete |
VoidCallback? |
null |
Called when animation finishes |
ποΈ Advanced Features
Grouped Animations
Coordinate multiple NumberFlow widgets:
NumberFlowGroup.row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
Text('Price'),
NumberFlow(
value: stockPrice,
prefix: '\$',
decimalPlaces: 2,
),
],
),
Column(
children: [
Text('Change'),
NumberFlow(
value: changePercent,
suffix: '%',
showSign: true,
style: TextStyle(
color: changePercent >= 0 ? Colors.green : Colors.red,
),
),
],
),
],
)
Custom Styling Examples
Gradient Text Effect
NumberFlow(
value: myValue,
style: TextStyle(
fontSize: 48,
fontWeight: FontWeight.bold,
foreground: Paint()
..shader = LinearGradient(
colors: [Colors.blue, Colors.purple],
).createShader(Rect.fromLTWH(0.0, 0.0, 200.0, 70.0)),
),
)
Different Styles for Components
NumberFlow(
value: 1234.56,
prefix: '\$',
suffix: ' USD',
style: TextStyle(fontSize: 32, color: Colors.green),
prefixStyle: TextStyle(fontSize: 24, color: Colors.grey),
suffixStyle: TextStyle(fontSize: 20, color: Colors.grey),
)
π± Real-World Use Cases
E-commerce Cart Total
NumberFlow(
value: cartTotal,
prefix: '\$',
decimalPlaces: 2,
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
spinCurve: NumberFlowCurves.smoothSpin,
)
Live Statistics Dashboard
Column(
children: [
NumberFlow(
value: activeUsers,
suffix: ' users online',
notation: NumberNotation.compact,
),
NumberFlow(
value: revenue,
prefix: '\$',
notation: NumberNotation.compact,
decimalPlaces: 1,
),
],
)
Gaming Score Display
NumberFlow(
value: playerScore,
style: TextStyle(
fontSize: 36,
fontWeight: FontWeight.bold,
color: Colors.amber,
),
spinCurve: NumberFlowCurves.bounce,
)
Financial Trading Interface
NumberFlow(
value: stockPrice,
prefix: '\$',
decimalPlaces: 2,
showSign: true,
trend: NumberFlowTrend.auto,
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.w600,
color: stockPrice >= previousPrice ? Colors.green : Colors.red,
),
)
π¨ Design Philosophy
NumberFlow follows these design principles:
π Smooth & Natural
- All animations use carefully crafted curves
- Transitions feel organic and pleasant
- No jarring or abrupt movements
π― Performance First
- Optimized for 60fps on all devices
- Minimal computational overhead
- Hardware-accelerated when possible
βΏ Accessible by Default
- Respects system motion preferences
- Works with screen readers
- Follows Flutter accessibility guidelines
π¨ Visually Polished
- Faded edges during width transitions
- Coordinated timing across all elements
- Professional appearance out of the box
π§ Migration & Compatibility
From Basic Text Widgets
// Before
Text('${myNumber.toStringAsFixed(2)}')
// After
NumberFlow(
value: myNumber,
decimalPlaces: 2,
)
Performance Considerations
- Use
animated: false
for static displays - Consider
isolate: true
for independent animations - Set
respectMotionPreference: false
if motion is essential
π€ Contributing
We welcome contributions! Here's how you can help:
- π Bug Reports: Open an issue with detailed reproduction steps
- β¨ Feature Requests: Suggest improvements or new features
- π§ Pull Requests: Submit code improvements or fixes
- π Documentation: Help improve examples and guides
Development Setup
git clone https://github.com/aghyad97/number-flow-flutter
cd number_flow
flutter packages get
cd example && flutter run
π License
This project is licensed under the MIT License - see the LICENSE file for details.
π Inspiration & Credits
This library is inspired by and aims to be a faithful Flutter port of the excellent number-flow library by Max Barvian.
Made with β€οΈ for the Flutter community
β Star on GitHub β’ π¦ View on pub.flutter-io.cn β’ π Report Issues