EditText append is duplicating numbers on SDK 31

278 views Asked by At

NOTE: This seems to only be happening in Android 12 (SDK 31)

I have a pretty complex use case for a TextWatcher in which I need to change text as the user types, however I may need to change more than just the character they just typed. For that reason I cannot use a InputFilter.

For this example to highlight the error I am seeing I have simplified my use case. I would just like to add a space after every character typed.

In my TextWatcher:

override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
   editText.removeTextChangedListener(this)
   addSpace(s, start, before, count)
   editText.addTextChangedListener(this)
}

private fun addSpace(s: CharSequence?, start: Int, before: Int, count: Int) {
   val text = s ?: return
   val spaced = "$text  "
   editText.text.clear()
   editText.text.append(spaced)
}

Note: I am using clear() and append() to avoid the keyboard from switching. If I use setText(), will switch back to the default keyboard.

This works just fine when adding letters:

enter image description here

However when adding numbers, it will duplicate each number. Adding some logging, it seems onTextChanged is being called again after my changes are complete and I re-add the listener.

enter image description here

Again this works just fine on SDK 30, and SDK 32, so it seems Android fixed the regression, but does not yet have a patch for SDK 31. Has anyone run into this? Know if there is an existing ticket I can follow? Having trouble finding any reference to this.

UPDATE: Running into the same issue using afterTextChanged(...)

override fun afterTextChanged(s: Editable?) {
   editText.removeTextChangedListener(this)
   addSpace(s)
   editText.addTextChangedListener(this)
}

private fun addSpace(s: Editable?) {
   val text = s ?: return
   val spaced = "$text  "
   s.clear()
   s.append(spaced)
}
1

There are 1 answers

4
Cheticamp On

According to the documentation forTextWatcher#onTextChanged:

This method is called to notify you that, within s, the count characters beginning at start have just replaced old text that had length before. It is an error to attempt to make changes to s from this callback.

The emphasis is mine. s: CharSequence? and editText.text refer to the same structure, so your code is making prohibited changes with, it seems, unpredictable results.