Skip to content

Instantly share code, notes, and snippets.

@hleinone
Last active November 30, 2023 14:03
Show Gist options
  • Star 25 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save hleinone/5b445e5475ca9f8a3bdc6a44998f4edd to your computer and use it in GitHub Desktop.
Save hleinone/5b445e5475ca9f8a3bdc6a44998f4edd to your computer and use it in GitHub Desktop.
Android EditText TextWatcher for formatting credit card number made with Kotlin
class CreditCardNumberFormattingTextWatcher : TextWatcher {
private var current = ""
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
}
override fun afterTextChanged(s: Editable) {
if (s.toString() != current) {
val userInput = s.toString().replace(nonDigits,"")
if (userInput.length <= 16) {
current = userInput.chunked(4).joinToString(" ")
s.filters = arrayOfNulls<InputFilter>(0)
}
s.replace(0, s.length, current, 0, current.length)
}
}
companion object {
private val nonDigits = Regex("[^\\d]")
}
}
@sharmadev2506
Copy link

Worked like charm. Thanks

@olala2288
Copy link

Thanks

@Mun0n
Copy link

Mun0n commented Jan 30, 2020

You can refactor this part of the code

val userInput = s.toString().replace("[^\\d]".toRegex(), "")
            if (userInput.length <= 16) {
                val sb = StringBuilder()
                for (i in 0..userInput.length - 1) {
                    if (i % 4 == 0 && i > 0) {
                        sb.append(" ")
                    }
                    sb.append(userInput[i])
                }
                current = sb.toString()

using something like

current = userInput.replace(" ","").chunk(2).jointString(" ")

@Mun0n
Copy link

Mun0n commented Jan 30, 2020

And a question

Why is needed this line? If I remove it, the format doesn't work

s.filters = arrayOfNulls(0)

@hleinone
Copy link
Author

@Mun0n Thanks for the suggestion, that simplified it quite a bit. I honestly don't remember why the filters need to be set, nor why emptyArray wouldn't be sufficient. 🤷‍♂️

@pokemonni01
Copy link

@Mun0n Thanks for the suggestion, that simplified it quite a bit. I honestly don't remember why the filters need to be set, nor why emptyArray wouldn't be sufficient. 🤷‍♂️

this line is needed if you set inputType as a number for edit text in xml file. cause number input type is not accept space.

@Biyane
Copy link

Biyane commented May 13, 2022

how this code does't go into infinite loop? i think the answer is in s.filters = arrayOfNulls<InputFilter>(0) but i cannot figure out

@hleinone
Copy link
Author

how this code does't go into infinite loop? i think the answer is in s.filters = arrayOfNulls<InputFilter>(0) but i cannot figure out

if (s.toString() != current) will prevent that.

@ShaunakSrivastava
Copy link

Work like charm, Thanks man!

@mohsenmdb
Copy link

You saved my day, Thanks man!

@hleinone
Copy link
Author

hleinone commented Jan 3, 2023

@mohsenmdb Cheers, my pleasure!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment