Search code examples
androidkotlintextwatcher

TextWatcher set min and max values


im trying to make an imput to be limited to a range of numbers using the TextWatcher and force the min and max if user try to go out of range. Works almost as expected but on a delete, allowing a visually empty text. How can i avoid that?

inputVal.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) {     //s=""
            var curVal = s.toString().toIntOrNull()?:5  //curVal=5
            if (curVal <  5){
                curVal = 5
                s.replace(0,s.length,"5")  <- problem here, not replacing cuz s.length=0
            }else if (curVal >50){
                curVal = 50
                s.replace(0,s.length,"50")
            }

            //some other things to do based on 'curVal'
        }})

update what i need is, for example, u have a '20' and adds a 0 (will be 200) transform it to a '50'; and if delete a 0 (being 2) force a 5 in the input.


Solution

  • Well, after testing i could make it work, here is the code:

    class NumberWatcher(private val mMin: Int, private val mMax: Int)
    :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) {
            Log.d("TextWatcher","Triggered '$s'")
            if (s.isEmpty() || s.toString().toInt() < mMin){
                s.replace(0, s.length, mMin.toString())
                return //will retrigger after the change, to avoid double excecution
            }else if (s.toString().toInt() > mMax){
                s.replace(0, s.length, mMax.toString())
                return //will retrigger after the change, to avoid double excecution
            }
    
            Log.d("TextWatcher","Do some things with '$s'")
            //do whatever
        }
    }
    

    usage:

    editText.addTextChangedListener(NumberWatcher(5,50))
    

    The log:

    D/TextWatcher: Triggered '45'
    D/TextWatcher: Do some things with '45'
    D/TextWatcher: Triggered '4'
    D/TextWatcher: Triggered '5'
    D/TextWatcher: Do some things with '5'
    D/TextWatcher: Triggered '95'
    D/TextWatcher: Triggered '50'
    D/TextWatcher: Do some things with '50'
    D/TextWatcher: Triggered '0'
    D/TextWatcher: Triggered '5'
    D/TextWatcher: Do some things with '5'
    D/TextWatcher: Triggered '35'
    D/TextWatcher: Do some things with '35'
    D/TextWatcher: Triggered ''
    D/TextWatcher: Triggered '5'
    D/TextWatcher: Do some things with '5'