number_flow 1.0.4

SDKflutter
Platformandroidioswindowslinuxmacosweb

An animated number component for Flutter, inspired by the number-flow library. Smoothly transitions between number values with customizable animations.

NumberFlow for Flutter

Flutter pub package License: MIT

✨ 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

NumberFlow 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

FeatureDescription
🎯 Smooth Digit AnimationsEach digit spins individually with perfect timing
🎨 Randomized DirectionsDigits spin in random directions for dynamic effects
📏 Animated Width TransitionsSmooth expansion/contraction with faded edges
High PerformanceOptimized for 60fps animations
🎛️ Highly CustomizableControl timing, curves, styling, and behavior
📱 Accessibility SupportRespects motion preferences automatically
🔧 Advanced FormattingPrefix/suffix, decimals, grouping, compact notation
🎪 Custom Animation CurvesBuilt-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.23M1.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

ParameterTypeDefaultDescription
valuenumrequiredThe number to display and animate
styleTextStyle?nullText styling for the number
animatedbooltrueEnable/disable all animations

Text & Formatting

ParameterTypeDefaultDescription
prefixString?nullText before the number (e.g., "$")
suffixString?nullText after the number (e.g., " USD")
prefixStyleTextStyle?nullCustom styling for prefix
suffixStyleTextStyle?nullCustom styling for suffix
decimalPlacesint?nullFixed decimal places
useGroupSeparatorbooltrueAdd commas for thousands
showSignboolfalseShow + for positive numbers
localeString?nullLocale for number formatting

Number Notation

ParameterTypeDefaultDescription
notationNumberNotationstandardNumber format style

NumberNotation Options:

  • NumberNotation.standard1234567
  • NumberNotation.compact1.23M
  • NumberNotation.scientific1.23e6
  • NumberNotation.engineering1.235e6

Animation Control

ParameterTypeDefaultDescription
transformDurationDuration600msWidth transition timing
spinDurationDuration600msDigit spin timing
opacityDurationDuration350msFade transition timing
transformCurveCurveeaseOutWidth animation curve
spinCurveCurveeaseOutDigit spin curve
opacityCurveCurveeaseOutOpacity animation curve

Animation Behavior

ParameterTypeDefaultDescription
trendNumberFlowTrendautoAnimation direction preference
isolateboolfalseDisable group coordination
respectMotionPreferencebooltrueHonor accessibility settings
willChangeboolfalseHint for performance optimization

NumberFlowTrend Options:

  • NumberFlowTrend.auto → Direction based on value change
  • NumberFlowTrend.up → Always animate upward
  • NumberFlowTrend.down → Always animate downward

Callbacks

ParameterTypeDefaultDescription
onAnimationStartVoidCallback?nullCalled when animation begins
onAnimationCompleteVoidCallback?nullCalled 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:

  1. 🐛 Bug Reports: Open an issue with detailed reproduction steps
  2. ✨ Feature Requests: Suggest improvements or new features
  3. 🔧 Pull Requests: Submit code improvements or fixes
  4. 📖 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.dev🐛 Report Issues