简体   繁体   中英

Filter Input in Real-Time?

I have an EditText (accepts 0-9) with a listener. I want to grab input as it's entered, apply a calculation, and display it in the same EditText box.

The box initially displays $0.00. When the user inputs a 2, I want to grab that from the box, parse it to remove the $ and decimal, convert it to an int... divide it by 100 and put a $ in front of it. After setText, it should display $0.02. If they then press 5, I'll grab it, parse it, end up with 25, do the math and it should display $0.25, etc.

I don't know if this is the best way, I'm open to new ideas. Here is my current code:

mEditPrice.addTextChangedListener(new TextWatcher(){
        DecimalFormat dec = new DecimalFormat("0.00");
        @Override
        public void afterTextChanged(Editable arg0) {
        }
        @Override
        public void beforeTextChanged(CharSequence s, int start,
                int count, int after) {
        }
        @Override
        public void onTextChanged(CharSequence s, int start,
                int before, int count) {
            String userInput = mEditPrice.getText().toString().replaceAll("[^\\d]", "");
            int userInputInt = Integer.parseInt(userInput);
            mEditPrice.setText("$"+dec.format(userInputInt / 100));
        }

There's a few issues to deal with here before you can achieve the kind of functionality you desire.

  1. Whenever you deal with a TextWatcher you need to be careful when setting the text of the EditText object being watched. The reason for this is that every time you call setText on it, it will trigger the watcher again, causing your code to go into an infinite loop.

    To prevent this, you should set the value of text you want to set into a variable outside of the onTextChanged method. When entering the method, check against this variable and only perform your processing code if the value is different from the CharSequence.

  2. The integer variable userInputInt, when divided by 100, will be equal to zero.

    This should be changed to a double to produce values like 0.02 etc.

  3. After those changes we can get the EditText to show $0.02 after entering a 2. But because we have set the value of the EditText in code, the next entry into the EditText will be added to the beginning of the text. Then if we enter a '5' we get $50.02.

    To overcome this, the last thing we need to do is set the position of the EditText to the end of the string, using the set position method.

Here's the final solution:

private String value;

mEditPrice.addTextChangedListener(new TextWatcher(){
    DecimalFormat dec = new DecimalFormat("0.00");

    @Override
    public void afterTextChanged(Editable arg0) {
    }

    @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 (!s.toString().equals(value)){
            String userInput = mEditPrice.getText().toString().replaceAll("[^\\d]", "");
            double userInputDouble = Double.parseDouble(userInput);
            value = ("$"+dec.format(userInputDouble / 100));

            mEditPrice.setText(value);
            mEditPrice.setSelection(value.length());
        }
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM