RollingNumbers is a Kotlin Multiplatform Compose library that animates text changes by rolling individual characters vertically β just like a odometer, an old school cash register, or those nostalgic airport split-flap boards.
Whether youβre showing stock prices, countdowns, money, or even flight numbers,
RollingNumbers makes every change feel satisfyingly alive with Levenshtein distance effect!
It also comes with a separate ready-to-use CurrencyRollingNumbers for beautifully animated,
locale-friendly money displays.
| Integer | Decimal |
|---|---|
Integer.mp4 |
Decimal.mp4 |
| Currency | Alphanumeric |
|---|---|
screen-20250818-192538.mp4 |
Alphanumeric.mp4 |
- π’ Animate anything β numbers, letters, symbols, emojisβ¦ if itβs a character, it can roll.
- π° Built-in currency mode β grouping separators, decimal points, and currency symbol placement (front or back) out of the box.
βοΈ Smart direction detection β rolls up when values go up, down when they drop.- π― Custom character sets β hex digits, flight numbers, scoreboard lettersβ¦ your animation path, your rules.
- π¨ Fully styleable β integrates seamlessly with Composeβs
TextStyle. - β‘ Adjustable speed β from dramatic slow rolls to rapid-fire flicks.
- πͺΆ Lightweight & clean β minimal dependencies, easy to drop into any project.
- π KMP ready β works across Android, iOS, Desktop and WASM.
- π§ Levenshtein-powered animation β calculates the smoothest, shortest scroll path between states.
- βΏ Accessible β screen readers announce the full target value as a single unit, no per-character noise.
- Inspired by Robinhood Ticker library β but built for the modern Kotlin Multiplatform Compose world.
- Fully Kotlin Multiplatform β the same rolling goodness on Android, iOS and Desktop.
- Comes with two ready-made components:
RollingNumbersfor any kind of textCurrencyRollingNumbersfor perfectly formatted animated amounts with currency.
- Supports alphanumeric and custom sets β perfect for flight numbers, scoreboard codes, or creative displays.
- Optimized for performance while still feeling smooth and fun to watch.
Add the dependency in your build.gradle.kts:
Add the mavenCentral repository to your settings.gradle.kts file:
dependencyResolutionManagement {
repositories {
mavenCentral()
}
}Add the dependency:
dependencies {
implementation "com.dontsaybojio:rollingnumbers:X.X.X"
}RollingNumbers(
text = amount,
characterLists = listOf(Utils.provideNumberString()),
animationDuration = DefaultAnimationDuration.Default.duration,
)CurrencyRollingNumbers(
amount = amount,
characterLists = listOf(Utils.provideNumberString()),
animationDuration = DefaultAnimationDuration.Default.duration,
)RollingNumbers(
text = text,
characterLists = Utils.provideAlphanumericList(),
animationDuration = DefaultAnimationDuration.Slow.duration,
)| Parameter | Type | Default | Description |
|---|---|---|---|
text |
String |
required | The text to display and animate. |
modifier |
Modifier |
Modifier |
Compose modifier for layout/styling. |
characterLists |
List<String> |
listOf(Utils.provideNumberString()) |
List of character sequences defining animation paths. |
animationDuration |
Int |
DefaultAnimationDuration.Default.duration |
Duration of the scroll animation in milliseconds. |
textStyle |
TextStyle |
LocalTextStyle.current |
Style applied to the text. |
scrollingDirection |
ScrollingDirection |
Any |
Force scroll direction: Up, Down, or Any. |
animateChanges |
Boolean |
true |
Whether to animate changes or update instantly. |
| Parameter | Type | Default | Description |
|---|---|---|---|
amount |
Double |
required | Target amount to display. |
modifier |
Modifier |
Modifier |
Compose modifier for layout/styling. |
characterLists |
List<String> |
listOf(Utils.provideNumberString()) |
List of character sequences defining animation paths. |
animationDuration |
Int |
DefaultAnimationDuration.Default.duration |
Duration of the scroll animation in milliseconds. |
textStyle |
TextStyle |
LocalTextStyle.current |
Style applied to the text. |
positiveSignedSymbolColor |
Color |
textStyle's colour | Positive signed symbol colour. |
negativeSignedSymbolColor |
Color |
textStyle's colour | Negative signed symbol colour. |
animateChanges |
Boolean |
true |
Whether to animate changes or update instantly. |
decimals |
Int |
2 |
Number of decimal places to format. |
currencySymbol |
String |
"$" |
Currency symbol. |
spacingInBetweenCurrencySymbol |
Dp |
8.dp |
Spacing in dp between currency symbol and RollingNumbers. |
spacingInBetweenSignedSymbol |
Dp |
8.dp |
Spacing in dp between signed symbol and RollingNumbers |
showPositiveSignedSymbol |
Boolean | false | Show signed symbol for positive amount |
isCurrencySymbolInFront |
Boolean |
Locale preference | Whether the currency symbol appears before the number. |
decimalSeparator |
Char |
Locale preference | Decimal separator character. |
groupingSeparator |
Char |
Locale preference | Thousands separator character. |
| Attribute | Type | Value |
|---|---|---|
Slow |
Int |
3_500 |
Medium (Default) |
Int |
2_000 |
Fast |
Int |
1_000 |
The library uses:
β’ Levenshtein distance to determine minimal scrolling changes between the current and target text.
β’ AnimatedCharacterColumn for per-character scroll animation.
β’ clipToBounds() to keep animations inside their columns.
β’ Multiple Character Sets: You can pass multiple strings in characterLists if you want certain characters to scroll independently (e.g., digits and symbols in different sequences).
β’ Custom Direction Control:
For number-based animations, use ScrollingDirection.Up or ScrollingDirection.Down to force a
scroll direction or it can be ScrollingDirection.Any for the nearest distance.
β’ Accessibility:
Both RollingNumbers and CurrencyRollingNumbers use clearAndSetSemantics to expose a single
contentDescription to screen readers. This ensures the complete target value is announced as one
coherent unit, rather than individual animated characters being read separately.
Pull requests are welcome! If you find a bug or have a feature request, please open an issue on GitHub.