How to make EditText accept input in format:
4digit 4digit 4digit 4digit
I tried Custom format edit text input android to acc
This is my implementation base on Igor Tyulkanov's idea, it has a small improvement that fix the cursor position problem
class CardNumbersInputWatcher(private val editText: EditText) : TextWatcher {
companion object {
private const val TOTAL_SYMBOLS = 19
private const val DIVIDER_DISTANCE = 4
private const val DIVIDER = ' '
}
override fun afterTextChanged(s: Editable) {
if (!isInputCorrect(s, TOTAL_SYMBOLS, DIVIDER_DISTANCE, DIVIDER)) {
val beforeCurPos = editText.selectionStart
val beforeLength = s.length
s.replace(0, s.length, buildCorrectString(s, TOTAL_SYMBOLS, DIVIDER_DISTANCE, DIVIDER))
if (beforeLength > TOTAL_SYMBOLS && beforeCurPos <= s.length && editText.selectionStart < beforeCurPos) {
editText.setSelection(beforeCurPos)
}
}
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit
}
private fun isInputCorrect(s: Editable, totalSymbols: Int, dividerDistance: Int, divider: Char): Boolean {
if (s.length > totalSymbols) {
return false
}
return s.withIndex().all { (index, c) ->
if (index != 0 && ((index + 1) % (dividerDistance + 1) == 0)) {
// it should be divider
c == divider
} else {
c.isDigit()
}
}
}
private fun buildCorrectString(s: Editable, totalSymbols: Int, dividerDistance: Int, divider: Char): String {
return buildString {
for (c in s) {
if (length >= totalSymbols) break
if (!c.isDigit()) continue
if (length > 0 && ((length + 1) % (dividerDistance + 1)) == 0) append(divider)
append(c)
}
}
}