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
MultiCurrencyFormatter
in 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.underlyingDecimalFormat
If you just need access to the underlying DecimalFormat
s 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.