0

Trying to change color of English text in EditText field's input. Add Textwatcher in Edittext and call method in afterTextchanged method.

val regEng = Pattern.compile("[a-zA-Z]")

var editWatcher = object : TextWatcher {
    override fun afterTextChanged(p0: Editable?) {
        onChanged()
    }

    override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
    }

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

}

 private fun onChanged() {
    var spanString = SpannableStringBuilder()
    var input = et_form.text.toString()

    for (i in 0 until input.length) {
        val char = input[i].toString()
        var matcher = regEng.matcher(char)
        if (matcher.find()) {
            val engspan = SpannableString(char).apply {
                setSpan(ForegroundColorSpan(Color.RED), matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
            }
            spanString.append(engspan)
        } else {
            val normal = SpannableString(char).apply {
                setSpan(ForegroundColorSpan(Color.BLACK), i, char.length - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
            }
            spanString.append(normal)
        }
    }
}

But it doesn't work and when I add code

edittext.text = spanString

It doesn't stop and keep calling onchanged method..

coooldoggy
  • 47
  • 5

2 Answers2

0

Since in each edit in editText you are changing the string. So onChange will be called every time. So to stop looping through the onChange you need to setup a criteria. Which could be:

private previousLength = 0


if(input.length != previousLength) {
  onChanged()
}

And after every change is completed you update

 previousLength = input.length;
Navinpd
  • 772
  • 7
  • 15
0

I suggest you to use span to prevent infinite calls of listeners and pass editable to onChanged() method.

private fun onChanged(s: Editable)  {

    if(s.isEmpty() || s.getSpans(0,s.length,YourSpanClass::class.java).isNotEmpty()
          return

    val span = YourSpanClass()
    s.setSpan(span,0,1,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)

    // do whatever you want on s and update it

    s.removeSpan(span)
}

Explanation: When you set span for the first time, until your changes are over and remove that span, it always returns from the first line of the code, thus infinite listener calls will be prevented. When span is removed, then changes of s will be applied just for once.

If you will not copy s into another Spanned, you may use

class YourSpanClass: NoCopySpan
    
Y.Kakdas
  • 833
  • 7
  • 17