2

I have an EditBox and a TextView in an application. I want the TextView to convert numbers that I type into the EditBox to words as I'm typing ( onTextChanged() ) and show it. I made the class for converting numbers to words and it works correctly. I search for onTextChanged event and I found how to use it but I faced a problem.

Here is the code:

ed.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        try {

            String num = ed.getText().toString();
            String str = num.replace(",", "");
            double x = Double.parseDouble(str);
            String text = NumberFormat.getIntegerInstance(Locale.US).format(x);

            ed.setText(text);

            /*if (ed.length() != 0)
            {
                String numtoalph = NumToAlph.convert(x);
                tv.setText( numtoalph + tv.getText().toString());
            }*/

            NumToAlph numToAlph = new NumToAlph();
            String alph = NumToAlph.Convert(text, x);
            tv.setText(alph + " ریال");

        }
        catch (Exception ex)
        {
            tv.setText(ex.toString());
        }


        @Override
        public void afterTextChanged(Editable s) {}

});

*NumToAlph is the class

When I installed it on my phone and tried to type as I pressed the first button the app froze and after a minute I got a notification which said that

this app is using too much CPU

I tested the code, I mean this

try {

    String num = ed.getText().toString();
    String str = num.replace(",", "");
    double x = Double.parseDouble(str);
    String text = NumberFormat.getIntegerInstance(Locale.US).format(x);

    ed.setText(text);
    /*
    if (ed.length() != 0)
    {
        String numtoalph = NumToAlph.convert(x);
        tv.setText( numtoalph + tv.getText().toString());
    }
    */

    NumToAlph numToAlph = new NumToAlph();
    String alph = NumToAlph.Convert(text, x);
    tv.setText(alph + " ریال");
}
catch (Exception ex)
{
    tv.setText(ex.toString());
}

in a button click event and it worked fast and correctly. Does any one have an idea about this problem?

I have programmed this app for windows in C# before, and used this for textChanged event with no problems:

decimal Number;
if (decimal.TryParse(textBox1.Text, out Number))
{
    textBox1.Text = string.Format("{0:N0}", Number);
    textBox1.SelectionStart = textBox1.Text.Length;
}

try
{
    NumToAlph dd = new NumToAlph();
    string x = textBox1.Text.Replace(",", "").ToString();
    textBox2.Text = dd.num2str(x) + " ریال";
}
catch (Exception ex)
{
    MessageBox.Show("Error", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
Bandreid
  • 2,727
  • 28
  • 47
A. Hajeb
  • 37
  • 1
  • 11

3 Answers3

3

The problem is that you are listening for a change in the EditText.

ed.addTextChangedListener(new TextWatcher() {

Then inside that function, you are changing the EditText content...

ed.setText(text);

You have created an infinite loop. You need to remove the ed.setText function calls from your TextWatcher interface function.

Knossos
  • 15,802
  • 10
  • 54
  • 91
1
ed.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

        }

        @Override
        public void afterTextChanged(Editable s) {
try {

                String num = ed.getText().toString();
                String str = num.replace(",", "");
                double x = Double.parseDouble(str);
                String text = NumberFormat.getIntegerInstance(Locale.US).format(x);

                ed.setText(text);
            /*if (ed.length() != 0)
            {
                String numtoalph = NumToAlph.convert(x);
                tv.setText( numtoalph + tv.getText().toString());
            }*/
                NumToAlph numToAlph = new NumToAlph();
                String alph = NumToAlph.Convert(text, x);
                tv.setText(alph + " ریال");
            }
            catch (Exception ex)
            {
                tv.setText(ex.toString());
            }
        }
    });
tiny sunlight
  • 6,231
  • 3
  • 21
  • 42
1

Maybe this helps:

if (!isChangedProgramatically) {
    String num = editText.getText().toString();
    if(!num.isEmpty()) {
        String str = num.replace(",", "");
        double x = Double.parseDouble(str);
        String text = NumberFormat.getIntegerInstance(Locale.US).format(x);

        isChangedProgramatically = true;
        editText.setText(text);
    }
} else {
    editText.setSelection(editText.getText().length());
    isChangedProgramatically = false;
}

isChangedProgramatically is a private boolean (default false) of your Activity.

cherry-wave
  • 731
  • 2
  • 6
  • 21
  • so isn't there any way to group numbers as you're typing in an editbox? – A. Hajeb Jan 18 '16 at 15:57
  • When you set the editText programatically it will again call your Listener, and that forever and forever. Maybe there is a way to tell the Listener if a change event was fired because of user input or your program. – cherry-wave Jan 18 '16 at 15:59
  • is it possible to make a tooltip and it become visible while typeing. do you know some resources to teach this kind of things? – A. Hajeb Jan 18 '16 at 16:25
  • A quick search revealed the following stackoverflow-thread. http://stackoverflow.com/a/13817777/4924595 I think standard tooltips as you know them from websites aren't that fancy on android. – cherry-wave Jan 18 '16 at 17:04
  • Could you tell me if the boolean helped with your problem and maybe rate the answer? Thanks^^ – cherry-wave Jan 18 '16 at 17:04
  • you mean put it in ontextchanged? – A. Hajeb Jan 18 '16 at 17:24
  • If you mean my answer post: yes. Just wrap a check around your manipulation of the edit text and only do this if the user entered something and not if you changed it by your own "setText" – cherry-wave Jan 18 '16 at 17:26
  • it works but it has a problem: if you type 123 it will show 321 – A. Hajeb Jan 18 '16 at 17:30
  • now I'm testing it. I reverse it but it only accept 3 digits and after it crashes. and you can't erase whatever you've entered – A. Hajeb Jan 18 '16 at 17:38
  • It is reversed because when you use `setText` androids sets the cursor to the beginning. Move your code to the `afterTextChanged` method and in my mentioned `else` part (where you set `isChangedProgramatically = false;`) just add: `editText.setSelection(editText.getText().length());` Remember to test if `num` is empty before doing your `replace` I updated my answer – cherry-wave Jan 18 '16 at 18:05
  • Did you remove your code for reversing it? Because you won't need it when using `editText.setSelection(editText.getText().length());` and I don't know what your code does^^ – cherry-wave Jan 18 '16 at 18:12
  • Could you write an answer/edit your question with your whole new code (and maybe the layout.xml) and the error message? – cherry-wave Jan 18 '16 at 18:17