It's more than 8 years passed and I am surprised, this issue isn't fixed yet...
I struggled with this simple issue since the most upvoted answer by @Martin lets typing multiple separators, i.e. user can type in "12,,,,,,12,1,,21,2,"
Also, the second concern is that on some devices comma is not shown on the numerical keyboard (or requires multiple pressing of a dot button)
Here is my workaround solution, which solves the mentioned problems and lets user typing '.' and ',', but in EditText he will see the only decimal separator which corresponds to current locale:
editText.apply { addTextChangedListener(DoubleTextChangedListener(this)) }
And the text watcher:
open class DoubleTextChangedListener(private val et: EditText) : TextWatcher {
init {
et.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
et.keyListener = DigitsKeyListener.getInstance("0123456789.,")
}
private val separator = DecimalFormatSymbols.getInstance().decimalSeparator
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
//empty
}
@CallSuper
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
et.run {
removeTextChangedListener(this@DoubleTextChangedListener)
val formatted = toLocalizedDecimal(s.toString(), separator)
setText(formatted)
setSelection(formatted.length)
addTextChangedListener(this@DoubleTextChangedListener)
}
}
override fun afterTextChanged(s: Editable?) {
// empty
}
/**
* Formats input to a decimal. Leaves the only separator (or none), which matches [separator].
* Examples:
* 1. [s]="12.12", [separator]=',' -> result= "12,12"
* 2. [s]="12.12", [separator]='.' -> result= "12.12"
* 4. [s]="12,12", [separator]='.' -> result= "12.12"
* 5. [s]="12,12,,..,,,,,34..,", [separator]=',' -> result= "12,1234"
* 6. [s]="12.12,,..,,,,,34..,", [separator]='.' -> result= "12.1234"
* 7. [s]="5" -> result= "5"
*/
private fun toLocalizedDecimal(s: String, separator: Char): String {
val cleared = s.replace(",", ".")
val splitted = cleared.split('.').filter { it.isNotBlank() }
return when (splitted.size) {
0 -> s
1 -> cleared.replace('.', separator).replaceAfter(separator, "")
2 -> splitted.joinToString(separator.toString())
else -> splitted[0]
.plus(separator)
.plus(splitted.subList(1, splitted.size - 1).joinToString(""))
}
}
}