EditText cursor position on addTextChangedListener with currency format

229 Views Asked by At

Is it possible to place cursor on selected position after changing the EditText content ? I've made these codes :

binding.editText1.addTextChangedListener(object : TextWatcher {

override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {       }

override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}

override fun afterTextChanged(s: Editable?) {
         val stringText = s.toString()

         if (stringText != current) {
              binding.editText1.removeTextChangedListener(this)

              val localeid = Locale("in", "ID")
              val format1 = NumberFormat.getInstance(localeid) as DecimalFormat
              format1.applyPattern("#,###.##")

              val doublecont : Double
              val cont = binding.editText1.text.toString().trim()
              doublecont = if (cont.isNotEmpty()) {
                        
            
           cont.replace("\\.","").replace(",","").replace(".","").toDouble()
                    } else {
                        0.0
                    }

              binding.editText1.setText(format1.format(doublecont))                 
             binding.editText1.setSelection(binding.editText1.text!!.length)
              binding.editText1.addTextChangedListener(this)
         } else {
              binding.editText1.setText("0")
         }
     }
})

I'm still confused with setSelection(), the result that I get from the codes above is the cursor will go to the end of EditText's character. What I want is when I move the cursor to position X, and type any number on it, the cursor will stay behind the newest number/character. Any idea for it ?

1

There are 1 best solutions below

0
cactustictacs On

You're explicitly setting the cursor position to the end of the EditText with setSelection(binding.editText1.text!!.length). Remember, this is happening in the _after_TextChanged callback, so the new text has already been added.

You need to handle this in one of the other methods, which tell you the position where the change is happening (start), and how many characters are replacing how many existing ones (count means different things depending on which method it is). This way you can work out where the cursor needs to be.

I don't remember offhand if you can do setSelection in these methods or if it'll be overwritten later, but one thing you can do is set a temporary value inside the TextWatcher object:

object : TextWatcher {
    var selectionPosition: Int? = null

Then you can set that in the earlier callback, and use it in afterTextChanged. Basically working out where the cursor will need to go, and then later setting that position. And clear it when you're done - but if you always set it, it doesn't need to be nullable, since it'll always be set to the appropriate value before afterTextChanged fires.

Nice trick with temporarily removing the TextWatcher btw, I always add an updating flag to ignore changes. I'll have to use that next time!