1

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)
}
lostintranslation
  • 23,756
  • 50
  • 159
  • 262

1 Answers1

0

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.

Cheticamp
  • 61,413
  • 10
  • 78
  • 131
  • Not sure that is the case, with plenty of folks solving similar problems w/ onTextChange. Yet, worth a shot. I tried using afterTextChanged, same issue. Works on 30 and 32, bug on 31. – lostintranslation Feb 04 '22 at 22:46
  • @lostintranslation I'd be curious to see your _afterTextChanged_ code that's not working. – Cheticamp Feb 04 '22 at 23:12
  • Sure added, it's not much different. Same result using editable to mod text or editText.setText(...). Works on 30 and 32, bug on 31. – lostintranslation Feb 04 '22 at 23:39
  • I think you have a case @lostintranslation. It seems random like a race condition. I am now curious if there will even be a fix for API 31. Post a link to the bug report if you submit one. – Cheticamp Feb 05 '22 at 00:52