A small Android library that dynamically reformats user input (from an EditText) for displaying currency values in any locale or currency. Java's DecimalFormat is used for formatting the numbers derived from user input.
- Android 4.1 (API 16)
Add Jitpack to your project build.gralde file
allprojects {
repositories {
maven { url 'https://jitpack.io' }
}
}
Then add this dependency to your app build.gradle file.
dependencies {
implementation 'com.github.jakeaaron:MultiCurrencyFormatter:1.0.0-alpha.1'
}
The MultiCurrencyFormatter allows configuration for the following fields/behaviors:
- Currency: Java Currency class used for formatting currency text values
- Currency symbol: Custom symbol to override the symbol associated with the Currency
- Locale: Locale used for formatting currency text values
- Resize text automatically
- Superscript the currency symbol
The following code snippet shows how to configure each field/behavior:
MultiCurrencyFormatter.newInstance(viewLifecycleOwner, editText)
.setCurrency(Currency.getInstance(Locale.JAPAN))
.setLocale(Locale.US)
.setSymbol("💸")
.setAutoResize(true)
.setSymbolSuperscript(true)Run the sample project to see the
MultiCurrencyFormatterin action.
The MultiCurrencyFormatter requires a LifecycleOwner and an EditText to create a new instance. This is all that is required to start formatting currency text.
MultiCurrencyFormatter.newInstance(viewLifecycleOwner, editText)MultiCurrencyFormatter listens for the LifecycleOwner#onDestroy event to clear out its reference to the EditText to avoid leaking its context. This means that the consumer doesn't need to worry about manually clearing out the view reference. When MultiCurrencyFormatter is instantiated, it registers the internal CurrencyTextWatcher with the EditText in order to listen to text input changes.
By default, the MultiCurrencyFormatter uses the default locale associated with the device to parse and format values. The locale dictates the Currency value, which then dictates the currency symbol. This means that in most cases, changing the locale will end up doing the correct thing in relation to the Currency and symbol. However, there is additional functionality in case more granular control is needed.
In order to change the Currency, Symbol, or Locale used by the formatter, use the corresponding methods on MultiCurrencyFormatter instance:
MultiCurrencyFormatter.newInstance(viewLifecycleOwner, editText)
.setLocale(Locale.CHINA)
.setSymbol("Â¥")
.setCurrency(Currency.getInstance(Locale.CHINA))or
MultiCurrencyFormatter.newInstance(viewLifecycleOwner, editText)
.setCurrencyFormatter(
CurrencyFormatter.getInstance(
currency,
symbol,
locale
)
)This is useful for updating the formatter in response to a user event (like selecting a new currency or locale from a menu/list, i.e. see sample project).
MultiCurrencyFormatter.textValue holds the formatted String information associated with the EditText, including the currency symbol.
MultiCurrencyFormatter.numberValue holds the BigDecimal value associated with the parsed EditText.text value.
MultiCurrencyFormatter.setAmount sets the text value.
For example:
MultiCurrencyFormatter.newInstance(viewLifecycleOwner, editText)
.setLocale(Locale.US)
.setAmount("50.00")
MultiCurrencyFormatter.textValue // $50.00
MultiCurrencyFormatter.numberValue // BigDecimal("50.00")
If you need additional callbacks into the EditText's TextWatcher use the addTextChangeListener method.
For example:
val editText = EditText(this)
val formatter = CurrencyFormatter.getInstance(Locale.ITALY)
val multiCurrencyFormatter = MultiCurrencyFormatter.newInstance(
this,
editText,
currencyFormatter = formatter
)
val customListener = object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
// do something important
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
}
multiCurrencyFormatter.addListener(customListener)
You may use the removeListener call to remove the listener, however, all listeners will get cleared on the LifecycleOwner#onDestroy event.
If you need access to the underlying DecimalFormat instance, it can be accessed from the CurrencyTextWatcher instance:
val multiCurrencyFormatter = MultiCurrencyFormatter.newInstance(viewLifecycleOwner, editText)
val decimalFormat = multiCurrencyFormatter.currencyTextWatcher.formatter.underlyingDecimalFormatIf you just need access to the underlying DecimalFormats decimalFormatSymbols, use the extension field MultiCurrencyFormatter.decimalFormatSymbols. This is useful for accessing the decimalSeparator, for instance.
Run the tests using an IDE like Intellij or Android Studio. Learn more.
If you have questions, concerns, bug reports, etc, please file an issue in this repository's Issue Tracker.
