animated_currency_field 0.5.0
animated_currency_field: ^0.5.0 copied to clipboard
A transparent Flutter text field where typed characters bloom from a blurry rising dot into the glyph. Tuned for amount entry, works for any text.
animated_currency_field #
A transparent Flutter text field where every typed character is born from a blurry rising dot at the baseline and blooms into the glyph. Built for amount entry โ digits + decimals + a currency prefix out of the box โ but it cheerfully accepts any text.
Each character looks like it was made of that soft dot rising from below. Backspace plays the same animation in reverse.
โจ Features #
- ๐ซ๏ธ Bloom-from-dot animation โ silky smoothstep envelopes, no linear seams.
- โฌ๏ธโฌ๏ธ Configurable dot origin โ let the dot rise from below or descend from above.
- ๐๏ธ Deep animation tuning โ speed, dot size, opacity, travel distance, expand scale, glyph rise distance, blur, scale, overshoot, curve.
- ๐ฒ First-class amount entry โ
digitsOnly,allowDecimal,maxDecimalPlaces, configurable decimal separator (.or,). - ๐ค Free-form text mode โ pass any
allowedPatternregex and your own keyboard type. - ๐ท๏ธ Prefix & suffix โ as text or arbitrary widgets, with independent fonts and visibility toggles.
- โ๏ธ Custom cursor โ color, visibility, plus a configurable placeholder.
- ๐จ Transparent by design โ sits on any background, you control every pixel of style.
- ๐งญ All Flutter platforms โ Android, iOS, web, macOS, Windows, Linux.
๐ฆ Installation #
Add to your pubspec.yaml:
dependencies:
animated_currency_field: ^0.4.0
Or:
flutter pub add animated_currency_field
Then:
import 'package:animated_currency_field/animated_currency_field.dart';
๐ Quick start #
AnimatedCurrencyField(
prefixText: '\$',
placeholder: '0',
allowDecimal: true,
maxDecimalPlaces: 2,
textStyle: const TextStyle(
fontSize: 96,
fontWeight: FontWeight.w700,
color: Colors.white,
),
)
That's it โ you get a centered amount field with a currency prefix, decimal support, a numeric keyboard with the decimal pad, and the bloom animation on every keystroke.
๐๏ธ Common recipes #
Amount with decimals (default) #
AnimatedCurrencyField(
prefixText: '\$',
allowDecimal: true,
maxDecimalPlaces: 2,
)
European locale (comma separator) #
AnimatedCurrencyField(
prefixText: 'โฌ',
allowDecimal: true,
maxDecimalPlaces: 2,
decimalSeparator: ',',
)
Whole numbers only #
AnimatedCurrencyField(
prefixText: 'โน',
allowDecimal: false,
maxLength: 9,
)
Free-form text #
AnimatedCurrencyField(
digitsOnly: false,
allowedPattern: RegExp(r'[A-Za-z0-9 ]'),
keyboardType: TextInputType.text,
showPrefix: false,
placeholder: 'Type something',
)
Listen to changes #
final controller = TextEditingController();
AnimatedCurrencyField(
controller: controller,
onChanged: (value) => print('Now: $value'),
onSubmitted: (value) => print('Submitted: $value'),
)
๐จ Animation tuning #
The bloom is governed by AnimatedCharacterStyle. Every parameter is live-tunable in the example app.
AnimatedCurrencyField(
animationDuration: const Duration(milliseconds: 500),
animationSpeed: 1.0, // multiplier on duration; >1 faster, <1 slower
characterStyle: const AnimatedCharacterStyle(
dotOrigin: DotOrigin.bottom, // or DotOrigin.top
dotSize: 16, // diameter in logical px
dotStartOpacity: 1.0, // 0..1
dotTravelDistance: 0.35, // fraction of glyph height
dotExpandScale: 2.4, // how much the dot grows as it dissolves
startBlur: 24, // glyph blur sigma at t=0
endBlur: 0, // glyph blur sigma at t=1
glyphRiseDistance: 0.55, // fraction of glyph height
startScale: 0.7, // glyph scale at t=0
overshootScale: 1.05, // brief overshoot before settling
curve: Curves.easeOutCubic,
),
)
Notable presets #
Ink drop โ heavier bloom from above:
AnimatedCharacterStyle(
dotOrigin: DotOrigin.top,
dotSize: 22,
dotTravelDistance: 0.9,
dotExpandScale: 4.0,
startBlur: 30,
)
Snappy โ subtle, fast:
AnimatedCharacterStyle(
dotSize: 10,
dotTravelDistance: 0.2,
dotExpandScale: 1.6,
startBlur: 14,
)
// also: animationSpeed: 1.8
๐งพ Full API #
AnimatedCurrencyField properties #
| Property | Type | Default | Description |
|---|---|---|---|
controller |
TextEditingController? |
null |
Optional external controller. |
focusNode |
FocusNode? |
null |
Optional external focus node. |
textStyle |
TextStyle? |
theme display | Style of the rendered glyphs. |
placeholder |
String? |
null |
Text shown when empty. |
placeholderStyle |
TextStyle? |
null |
Style for placeholder text. |
showPlaceholder |
bool |
true |
Master toggle for placeholder slot. |
textAlign |
TextAlign |
center |
Horizontal alignment of the content. |
cursorColor |
Color? |
text color | Cursor color. |
showCursor |
bool |
true |
Whether to render the blinking cursor. |
characterStyle |
AnimatedCharacterStyle |
const AnimatedCharacterStyle() |
Per-character animation tuning. |
animationDuration |
Duration |
420ms |
Base duration of a single character's animation. |
animationSpeed |
double |
1.0 |
Multiplier on animationDuration. |
digitsOnly |
bool |
true |
Restrict input to digits (+ separator if allowDecimal). |
allowDecimal |
bool |
false |
Allow a single decimal separator. |
maxDecimalPlaces |
int |
2 |
Cap on digits after the separator. |
decimalSeparator |
String |
'.' |
The separator character. |
allowedPattern |
RegExp? |
null |
Character whitelist when digitsOnly is false. |
maxLength |
int? |
null |
Cap on total character count. |
keyboardType |
TextInputType? |
inferred | Override the keyboard. |
showPrefix |
bool |
true |
Master toggle for prefix slot. |
prefixText |
String? |
null |
Convenience prefix string (e.g. '$'). |
prefixStyle |
TextStyle? |
falls back to textStyle |
Style for prefixText. |
prefix |
Widget? |
null |
Custom prefix widget (overrides prefixText). |
showSuffix |
bool |
true |
Master toggle for suffix slot. |
suffixText |
String? |
null |
Convenience suffix string. |
suffixStyle |
TextStyle? |
falls back to textStyle |
Style for suffixText. |
suffix |
Widget? |
null |
Custom suffix widget (overrides suffixText). |
autofocus |
bool |
false |
Focus on mount. |
onChanged |
ValueChanged<String>? |
null |
Called when the value changes. |
onSubmitted |
ValueChanged<String>? |
null |
Called when the user submits via keyboard. |
DotOrigin enum #
| Value | Meaning |
|---|---|
DotOrigin.bottom |
Dot rises from below the baseline (default). |
DotOrigin.top |
Dot descends from above the cap height. |
DecimalInputFormatter #
Exposed for reuse outside the widget โ same logic the field uses internally.
TextField(
inputFormatters: [
DecimalInputFormatter(maxDecimalPlaces: 2, separator: '.'),
],
)
๐งช Example app #
A complete playground with live sliders for every animation knob lives in example/lib/main.dart.
cd example
flutter create . # first time only โ generates platform folders
flutter run
๐ ๏ธ How it works #
Under the hood the widget hosts a real but visually hidden TextField to drive the IME, selection, paste, and input formatters. On every text change it diffs the previous and next strings (longest common prefix/suffix), keeps the identity of unchanged characters, and only animates the inserts and deletes โ so typing in the middle of a string doesn't replay the whole row.
Each character is its own AnimatedCharacter widget with its own AnimationController. Removed characters stay in their original slot and play the reverse animation in place before disposing โ so fast backspace stays smooth and there's no positional jumping.
๐ค Contributing #
Issues and pull requests welcome at github.com/JayGoti/animated_currency_field.
When filing a bug, please include:
- Flutter version (
flutter --version) - Platform you're on
- A minimal
AnimatedCurrencyFieldconfig that reproduces the issue - What you expected vs. what happened (a short screen recording is gold)
๐ License #
MIT โ see LICENSE.