51

I have an EditText with "text = 0.00". When I press the number 3, it should be like 0.03 and the second time when I press the number 5, the text should be 0.35. And 35.0, 35.09 like this. The EditText initially has the value of 0.00.

These are all done with the same EditText.

How do I achieve this? I have tried using addTextChangedListener() with TextWatcher().

0xCursor
  • 2,242
  • 4
  • 15
  • 33
Ria
  • 873
  • 1
  • 10
  • 25

6 Answers6

104

You can also try this:

EditText searchTo = (EditText)findViewById(R.id.medittext);
searchTo.addTextChangedListener(new TextWatcher() {
    @Override
    public void afterTextChanged(Editable s) {
        // TODO Auto-generated method stub
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        // TODO Auto-generated method stub
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        doSomething();
    } 
});
Druid
  • 6,423
  • 4
  • 41
  • 56
Khawar Raza
  • 15,870
  • 24
  • 70
  • 127
  • 4
    when i do setText() the onTextChanged is called again, how to prevent that? – M. Usman Khan Mar 03 '16 at 08:24
  • 5
    You cannot prevent onTextChanged from being called on setText event. You will have to do it yourself like using some booleans which set to true before setting text and in on ontextchanged, check for that boolean and decide whether to proceed with onTextChanged event or not. One more solution is to remove TextChangeListener before setting text and set it again after setting text. – Khawar Raza Mar 03 '16 at 08:46
  • Yes you cant prevent that. Google recommends to use [setSpan](https://developer.android.com/reference/android/text/Spannable.html) method if you need to know where changes were made – Anatolii Shuba Aug 14 '17 at 02:02
40

You have selected correct approach. You have to extend the class with TextWatcher and override afterTextChanged(),beforeTextChanged(), onTextChanged().

You have to write your desired logic in afterTextChanged() method to achieve functionality needed by you.

Ahmad
  • 69,608
  • 17
  • 111
  • 137
Roll no1
  • 1,315
  • 1
  • 16
  • 23
  • 3
    when i do setText() the afterTextChanged is called again, how to prevent that? – M. Usman Khan Mar 03 '16 at 08:24
  • 1
    Late comment but the docs on [`afterTextChanged`](https://developer.android.com/reference/android/text/TextWatcher.html#afterTextChanged(android.text.Editable)) warn about this situation, **It is legitimate to make further changes to s from this callback, but be careful not to get yourself into an infinite loop, because any changes you make will cause this method to be called again recursively.** so don't change s from here, I guess is the solution? – JimLohse Sep 19 '18 at 13:52
  • Is there a way to distinct when the text is changed by the user or by setText() method? – Donki Mar 26 '20 at 14:13
9

Here, I wrote something similar to what u need:

    inputBoxNumberEt.setText(".     ");
    inputBoxNumberEt.setSelection(inputBoxNumberEt.getText().length());
    inputBoxNumberEt.addTextChangedListener(new TextWatcher() {

        boolean ignoreChange = false;

        @Override
        public void afterTextChanged(Editable s) {
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start,
                                      int count, int after) {
        }

        @Override
        public void onTextChanged(CharSequence s, int start,
                                  int before, int count) {
            if (!ignoreChange) {
                String string = s.toString();
                string = string.replace(".", "");
                string = string.replace(" ", "");
                if (string.length() == 0)
                    string = ".     ";
                else if (string.length() == 1)
                    string = ".  " + string;
                else if (string.length() == 2)
                    string = "." + string;
                else if (string.length() > 2)
                    string = string.substring(0, string.length() - 2) + "." + string.substring(string.length() - 2, string.length());
                ignoreChange = true;
                inputBoxNumberEt.setText(string);
                inputBoxNumberEt.setSelection(inputBoxNumberEt.getText().length());
                ignoreChange = false;
            }
        }
    });
M. Usman Khan
  • 3,689
  • 1
  • 59
  • 69
2

put the logic in

afterTextChanged(Editable s) {
    string str = s.toString()
    // use the string str
}

documentation on TextWatcher

Dan Alboteanu
  • 9,404
  • 1
  • 52
  • 40
1

In Kotlin Android EditText listener is set using,

   val searchTo : EditText = findViewById(R.id.searchTo)
   searchTo.addTextChangedListener(object : TextWatcher {
    override fun afterTextChanged(s: Editable) {

        // you can call or do what you want with your EditText here

        // yourEditText...
    }

    override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
    override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
})
Rohith Murali
  • 5,551
  • 2
  • 25
  • 26
0

Here is the working Kotlin version.

  yourEditText.addTextChangedListener(object: TextWatcher {
    override fun afterTextChanged(s: Editable?) {
      // TODO Auto-generated method stub
    }

    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
      // TODO Auto-generated method stub
    }

    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
      doSomething()
    }
  })
Salman Nazir
  • 2,759
  • 2
  • 28
  • 42