number_flow_flutter 0.1.0 copy "number_flow_flutter: ^0.1.0" to clipboard
number_flow_flutter: ^0.1.0 copied to clipboard

Beautiful animated numbers for Flutter — digit-by-digit rolling transitions with locale-aware formatting, springs, and motion blur.

number_flow_flutter #

number_flow_flutter — animated rolling numbers demo

Beautiful, animated numbers for Flutter. When a value changes, each digit rolls to its new position like an odometer — with locale-aware formatting, smooth enter/exit transitions as the number grows or shrinks, an optional iOS-style spring, and velocity-based motion blur.

NumberFlow handles numbers (counters, currency, percentages, compact and scientific notation); TimeFlow handles clocks, countdowns, and stopwatches.

Features #

  • Digit-by-digit rolling — only the digits that changed animate; the rest stay put.
  • Locale-aware formatting — decimal, currency, percent, compact (1.2K), scientific (1.2×10³), and engineering notation, with correct grouping, numbering systems, and RTL.
  • Smooth reflow — digits slide to their new column and the box resizes when the number grows or shrinks; entering digits roll in, exiting digits fade out.
  • Curve or spring — a front-loaded easing curve by default, or an opt-in iOS-like spring with overshoot and velocity hand-off for interrupted rolls.
  • Motion blur — optional velocity-based blur while rolling (vertical and/or horizontal), fully tunable.
  • Scrub mode — drive the display from a ValueListenable<num> (a slider, chart scrubber, gesture) at high frequency without a rebuild per tick.
  • Accessible — exposes a plain-text semantics label; honors the platform reduce-motion setting.

Installation #

Add to your pubspec.yaml:

dependencies:
  number_flow_flutter: ^0.0.1

Then:

import 'package:number_flow_flutter/number_flow_flutter.dart';

Quick start #

NumberFlow(value: 1234)

That's it — whenever value changes on rebuild, the digits animate to the new number.

NumberFlow #

Formatting #

Pass a NumberFlowFormat to control how the value is rendered:

// Currency
NumberFlow(
  value: 1234.56,
  format: const NumberFlowFormat.currency(currencyCode: 'USD', symbol: r'$'),
  locale: 'en_US',
)

// Percent (0.0–1.0 → 0%–100%)
NumberFlow(value: 0.42, format: const NumberFlowFormat.percent())

// Compact — 1,234,567 → 1.2M
NumberFlow(
  value: 1234567,
  format: const NumberFlowFormat.compact(maxFraction: 1),
)

// Scientific — 12345 → 1.23×10⁴  (the exponent renders as a superscript)
NumberFlow(
  value: 12345,
  format: const NumberFlowFormat.scientific(maxFraction: 2),
)

// Engineering — exponent is always a multiple of 3
NumberFlow(value: 1500000, format: const NumberFlowFormat.engineering())

// Plain decimal with fraction bounds
NumberFlow(
  value: 3.14159,
  format: const NumberFlowFormat.decimal(minFraction: 2, maxFraction: 2),
)

Every format accepts a sign (SignDisplay.auto, always, exceptZero, negative, never) to control when the +/- sign shows.

Prefix, suffix, and trend #

NumberFlow(
  value: score,
  prefix: '~',
  suffix: ' pts',
  // Direction the digits roll. Omit to auto-detect from the value change.
  trend: 1, // 1 up, -1 down, 0 shortest path
)

For a custom rule, pass trendFn: (prev, next) => ... instead of trend.

Styling and layout #

NumberFlow(
  value: 1234,
  style: const TextStyle(fontSize: 48, fontWeight: FontWeight.w600),
  textAlign: TextAlignValue.end,
  direction: Direction.auto, // ltr / rtl / auto
  tabularNums: true,         // uniform digit width — no horizontal shift
)

Animation #

The roll uses a fixed-duration easing curve by default. Customize it, or opt into a spring:

// Custom curve timing
NumberFlow(
  value: v,
  spinTiming: const TimingConfig(
    duration: Duration(milliseconds: 700),
    curve: NumberFlowCurve(),
  ),
)

// iOS-like spring (overshoot + velocity hand-off on interrupt)
NumberFlow(value: v, spring: NumberFlowSpring.ios)

// Custom spring
NumberFlow(
  value: v,
  spring: const NumberFlowSpring(mass: 1, stiffness: 170, damping: 20),
)

Other animation knobs:

Property Description
animated Master switch; false snaps with no animation.
respectMotionPreference When true (default), honors the OS reduce-motion setting.
transformTiming Timing for horizontal reflow (digits sliding to new columns).
opacityTiming Enter/exit fade timing.
continuous Odometer mode: unchanged lower digits spin a full extra cycle on carry (needs a directional trend).
stagger Left-to-right delay per digit (higher digits lead).
wheelSpacing Vertical spacing between wheel glyphs (× line height).
mask Fade the top/bottom edges of the digit window.

Motion blur & squish #

Digits blur and compress while rolling fast, then sharpen and spring back as they settle:

NumberFlow(
  value: v,
  motionBlur: 8,               // max blur sigma (px) at peak speed
  motionBlurVelocityScale: 6,  // lower = blur ramps in sooner / stronger
  motionBlurThreshold: 0.5,    // roll speed below which no blur is applied
  digitSquish: 0.3,            // horizontal squish: scaleX → 1 - 0.3 at peak
)

The blur is a soft frosted blur over the whole digit that ramps up while it rolls fast and fades to fully crisp as it settles — so only the moving digits are blurred, never the settled ones.

digitSquish compresses a rolling digit horizontally (to 1 - digitSquish) at peak speed and springs it back to full width as it settles, for a snappy, motion-compressed feel. It only affects the digits that are actually moving.

With NumberFlowSpring.ios, motion blur, digit squish, and stagger all default to iOS-preset values automatically — a prominent blur (peak sigma 4, velocity scale 4), a 0.3 squish, and a left-to-right stagger. Pass explicit values to override any of them.

Per-digit constraints #

Cap individual wheels (e.g. a rating that only goes 0–5 in the ones place):

NumberFlow(
  value: rating,
  // position 0 = ones, 1 = tens, …
  digits: {0: const DigitConstraint(max: 5)},
)

Scrub mode #

For a value that updates faster than the widget can rebuild (a slider drag, a chart scrubber), drive it from a ValueListenable<num>. The widget re-formats each tick and rolls only the changed digits, repainting without a full rebuild unless the digit count changes:

final scrub = ValueNotifier<num>(0);

NumberFlow.scrub(
  value: scrub,
  format: const NumberFlowFormat.currency(currencyCode: 'USD', symbol: r'$'),
  tabularNums: true, // steady width for smooth scrubbing
)

// later, from a gesture:
scrub.value = newValue;

TimeFlow #

An animated clock, countdown, or stopwatch. It's prop-driven — the parent owns the ticking (a Timer, Ticker, or stream) and pushes new values.

// Explicit fields
TimeFlow(hours: 12, minutes: 30, seconds: 45)

// From a Duration (countdown / stopwatch)
TimeFlow.duration(
  elapsed,
  showHours: elapsed.inHours > 0,
  showCentiseconds: true,
)

// From a DateTime (wall clock)
TimeFlow.dateTime(DateTime.now(), showSeconds: true, is24Hour: false)

TimeFlow accepts the same animation properties as NumberFlow (spinTiming, spring, motionBlur, wheelSpacing, mask, …).

Callbacks #

Both widgets accept onAnimationsStart and onAnimationsFinish:

NumberFlow(
  value: v,
  onAnimationsStart: () => debugPrint('rolling'),
  onAnimationsFinish: () => debugPrint('settled'),
)

Accessibility #

Each widget exposes a plain-text semantics label of the formatted value (e.g. "$1,234.56", or "1.2E4" for scientific notation), so screen readers announce the number rather than individual rolling glyphs. When the platform reduce-motion setting is on, transitions snap instead of rolling (unless respectMotionPreference: false).

Example #

See the example/ app for an interactive gallery: counter, currency, percent, compact, scientific, a live stopwatch, a scrub slider, and sliders for every animation parameter.

License #

See the LICENSE file in the repository.

5
likes
160
points
0
downloads

Documentation

API reference

Publisher

verified publisherbriankariuki.com

Weekly Downloads

Beautiful animated numbers for Flutter — digit-by-digit rolling transitions with locale-aware formatting, springs, and motion blur.

Repository (GitHub)
View/report issues

Topics

#animation #number #counter #text #ui

License

MIT (license)

Dependencies

flutter, intl

More

Packages that depend on number_flow_flutter