Hot questions for Using Android EditText in android textwatcher

Top Java Programmings / Android EditText / android textwatcher

Question:

I am trying to add only two numbers after a decimal point input in an EditText.

So I implemented a TextWatcher to check the string during input.

The function I am using below works amazing but has one major flaw. When you input any value,then you add a decimal point,delete that decimal point and proceed to add more values,only 3 values are accepted as input.

Case example: I input 300. but then I realize I wanted to input 3001234567, so I delete the decimal point . and proceed to add 1234567 to 300, Only 123 will be accepted and the rest ignored.

How should i handle this? Any suggestions will be appreciated.

My code:

 price.addTextChangedListener(new TextWatcher() {
     public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {

     }

     public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {

     }

     public void afterTextChanged(Editable arg0) {
         if (arg0.length() > 0) {
             String str = price.getText().toString();
             price.setOnKeyListener(new View.OnKeyListener() {
                 public boolean onKey(View v, int keyCode, KeyEvent event) {
                     if (keyCode == KeyEvent.KEYCODE_DEL) {
                         count--;
                         InputFilter[] fArray = new InputFilter[1];
                         fArray[0] = new InputFilter.LengthFilter(100);
                         price.setFilters(fArray);
                         //change the edittext's maximum length to 100.
                         //If we didn't change this the edittext's maximum length will
                         //be number of digits we previously entered.
                     }
                     return false;
                 }
             });
             char t = str.charAt(arg0.length() - 1);
             if (t == '.') {
                 count = 0;
             }
             if (count >= 0) {
                 if (count == 2) {
                     InputFilter[] fArray = new InputFilter[1];
                     fArray[0] = new InputFilter.LengthFilter(arg0.length());
                     price.setFilters(fArray);
                     //prevent the edittext from accessing digits
                     //by setting maximum length as total number of digits                               we typed till now.
                 }
                  count++;
              }
          }
      }
  });

Answer:

Try this:

@Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
             String input = s.toString();
            if(input.contains(".") && s.charAt(s.length()-1) != '.'){
                if(input.indexOf(".") + 3 <= input.length()-1){
                    String formatted = input.substring(0, input.indexOf(".") + 3);
                    editReceiver.setText(formatted);
                    editReceiver.setSelection(formatted.length());
                }
            }else if(input.contains(",") && s.charAt(s.length()-1) != ','){
                if(input.indexOf(",") + 3 <= input.length()-1){
                    String formatted = input.substring(0, input.indexOf(",") + 3);
                    editReceiver.setText(formatted);
                    editReceiver.setSelection(formatted.length());
                }
            }
        }

Please note, german decimals are , seperated instead of . seperated You can remove that else part, if it is not needed.

Question:

Hello i'm writing this program to get user input and format to 0,000.00 for example the program works fine when i try 5,768.80 BUT it doesn't when i try 5,768.08 as you can see the problem is that i can't put a 0 in the cents place before any other number... here is my code:

package com.calculadorabss.gorydev.calculadorabolivaressoberanos;

import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;

import java.text.DecimalFormat;
import java.text.ParseException;

class NumberTextWatcher implements TextWatcher {

    private DecimalFormat df;
    private DecimalFormat dfnd;
    private boolean hasFractionalPart;

    private EditText et;
    //Dar formato al texto de entrada separando por comas
    public NumberTextWatcher(EditText et)
    {
        df = new DecimalFormat("#,###,##");
        df.setDecimalSeparatorAlwaysShown(true);
        dfnd = new DecimalFormat("#,###,##");
        this.et = et;
        hasFractionalPart = false;
    }

    @SuppressWarnings("unused")
    private static final String TAG = "NumberTextWatcher";

    public void afterTextChanged(Editable s)
    {
        et.removeTextChangedListener(this);

        try {
            int inilen, endlen;
            inilen = et.getText().length();

            String v = s.toString().replace(String.valueOf(df.getDecimalFormatSymbols().getGroupingSeparator()), "");
            Number n = df.parse(v);
            int cp = et.getSelectionStart();
            if (hasFractionalPart) {
                et.setText(df.format(n));
            } else {
                et.setText(dfnd.format(n));
            }
            endlen = et.getText().length();
            int sel = (cp + (endlen - inilen));
            if (sel > 0 && sel <= et.getText().length()) {
                et.setSelection(sel);
            } else {
                // place cursor at the end?
                et.setSelection(et.getText().length() - 1);
            }
        } catch (NumberFormatException nfe) {
            // do nothing?
        } catch (ParseException e) {
            // do nothing?
        }

        et.addTextChangedListener(this);
    }
}

i want the program to be able to receive 0 as cents for example 67,789.05


Answer:

Try this i think it work

public void afterTextChanged(Editable s)
    {
        et.removeTextChangedListener(this);

        try {
            int inilen, endlen;
            inilen = et.getText().length();

            String v = s.toString().replace(String.valueOf(df.getDecimalFormatSymbols().getGroupingSeparator()), "");
            hasFractionalPart = v.contains(".");
            Number n = df.parse(v);
            int cp = et.getSelectionStart();
            if (!hasFractionalPart) {
                et.setText(dfnd.format(n));
            }

            endlen = et.getText().length();
            int sel = (cp + (endlen - inilen));
            if (sel > 0 && sel <= et.getText().length()) {
                et.setSelection(sel);
            } else {
                // place cursor at the end?
                et.setSelection(et.getText().length() - 1);
            }
        } catch (NumberFormatException nfe) {
            // do nothing?
        } catch (ParseException e) {
            // do nothing?
        }

        et.addTextChangedListener(this);
    }

Question:

I'm trying to wrote android program which displays Greatest Common Divisor of two integers specified in two different EditText fields. First I've done it with button, everything worked (you can see onclick listener commented out in code below). Now I want to do this: app checks when both EditTexts are not empty and then automatically starts calculating and shows gcd. Buty app crashes when I start typing in any of EditText fields. Also I tried to add TextChangeListener only on one of EditTexts. Everything is good until I delete all input from one of the fields, then app crashes again. I'm only starting to understand android development and made this app mostly by modifying examples found on internet so maybe I did something wrong... Can anyone help me? Thanks

MainActivity.java

    public class MainActivity extends Activity 

{
    EditText a;
    EditText b;
    TextView gcdResult;
    Button calculateGcd;
    int a, b, gcdValue

    TextWatcher textWatcher = new TextWatcher(){
        @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){

            AutoCalculateGcd();

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {


        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        a = (EditText)findViewById(R.id.aText1);
        b = (EditText)findViewById(R.id.bText1);
        gcdResult = (TextView)findViewById(R.id.resultTextView1);
        calculateGcd = (Button)findViewById(R.id.calcButton1);

        /* calculateGcd.setOnClickListener(new OnClickListener(){
            public void onClick(View v){
                AutoCalculateRatio();
            }
        });*/

        a.addTextChangedListener(textWatcher);
        b.addTextChangedListener(textWatcher);

    }



    //Euclidean alghorithm to find gcd
    public static int gcd(int a, int b) {
        if (b == 0) return w;
        else return gcd(b a % b);

        }
    public static boolean isInputNotEmpty(EditText a, EditText b){
        String a = a.getText().toString();
        String b = b.getText().toString();
        if(a.equals("") && b.equals("") ){
             return false;
    }
    else{
        return true;
    }

    }
    public void AutoCalculateGcd(){
        if(isInputNotEmpty(a, b)){
            a = Integer.parseInt(width.getText().toString());
            b = Integer.parseInt(height.getText().toString());
            gcdValue = gcd(a, b);
            ratioResult.setText(Integer.toString(gcdValue));
        }
        else{
            //Toast.makeText(this, "No input", Toast.LENGTH_SHORT).show();
        }
    }
}

Answer:

Actually, you should replace

public static boolean isInputNotEmpty(EditText a, EditText b) {
    String a = a.getText().toString();
    String b = b.getText().toString();
    if (a.equals("") && b.equals("")) {
         return false;
    }
    else {
        return true;
    }
}

with

public static boolean isInputNotEmpty(EditText a, EditText b) {
    String a = a.getText().toString();
    String b = b.getText().toString();
    if (a.equals("") || b.equals("")) {
         return false;
    }
    else {
        return true;
    }
}

Or even

public static boolean isInputNotEmpty(EditText a, EditText b) {
    return !(a.getText().toString().isEmpty() || b.getText().toString().isEmpty());
}

Because you want to know if any ( || ) of them is empty, not if both (&&) are.

Question:

Description

I am developing one app in which I have registration page. Inside registration page, I am doing registration by getting user's full name and mobile number.

Problem

While getting user's full name in edit text sometimes the user is pressing space bar before type his/her name.

I need you disable space-bar key before typing any text white user start typing his name I want to enable space-bar key. So that user can enter space between his/her Middle name and Last name.

What I have tried?

Answer

I am using text watcher in edit text.

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

                inputLayoutname.setError(null);
            }

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

                System.out.println(TAG+" s :"+s+ " start :"+start+" Before : "+before+" Count: "+count);
                String str = s.toString();

                if(str.length() > 0 && str.contains(" "))
                {
                    user_name.setError("Space is not allowed");
                    user_name.setText("");
                }
            }

            @Override
            public void afterTextChanged(Editable s) {    

                if (user_name.getText().length() > 0)
                    inputLayoutname.setError(null);
            }
        });

What problem coming when I am implementing this code?

While user pressing firstly it automatically removing space suddenly. But when user trying to enter space between full name, it's again removing all text and showing empty edit text.

screen 1 while entering only space

Here I am entering my Name and want to enter last name or middle name of space

Here when I am entering space after my first name


Answer:

First, try to understand what he is trying to do

He is trying to prevent user typing leading spaces and not after entering text.

He doesn't want to trim username

Update your code from

if(str.length() > 0 && str.contains(" "))
                {
                    user_name.setError("Space is not allowed");
                    user_name.setText("");
                }

to

if(str.equals(" "))
                {
                    user_name.setError("Leading Space is not allowed");
                    user_name.setText("");
                }

It will prevent user typing any space before name

Question:

I want to add 3 decimal places currency formatting to EditText using TextWatcher at the beginning, value is 0.000 and the number should change right to left

eg: if I pressed 1,2,3,4,5 in order value should appear as this 12.345

following code is worked only for 2 decimal places. Please anyone helps me how to change this code for 3 decimal places or another solution

 public class CurrencyTextWatcher  implements TextWatcher {
    boolean mEditing;
    Context context;


    public CurrencyTextWatcher() {
        mEditing = false;
    }

    public synchronized void afterTextChanged(Editable s) {

        if(!mEditing) {
            mEditing = true;
            String digits = s.toString().replaceAll("\\D", "");
             NumberFormat nf = NumberFormat.getCurrencyInstance();

            try{
                String formatted = nf.format(Double.parseDouble(digits)/100);
                s.replace(0, s.length(), formatted);
            } catch (NumberFormatException nfe) {
                s.clear();
            }
            mEditing = false;
        }
    }

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

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

}

Answer:

Divide 1000 instead of 100 and also setMinimumFractionDigits for NumberFormat as 3.

public class CurrencyTextWatcher  implements TextWatcher {
    boolean mEditing;
    Context context;


    public CurrencyTextWatcher() {
        mEditing = false;
    }

    public synchronized void afterTextChanged(Editable s) {

        if(!mEditing) {
            mEditing = true;
            String digits = s.toString().replaceAll("\\D", "");
            NumberFormat nf = NumberFormat.getCurrencyInstance();
            nf.setMinimumFractionDigits(3);

            try{
                String formatted = nf.format(Double.parseDouble(digits)/1000);
                s.replace(0, s.length(), formatted);
            } catch (NumberFormatException nfe) {
                s.clear();
            }
            mEditing = false;
        }
    }

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

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

}

Question:

My FourDigitCardFormatWatcher add a space after every 4 numbers. I want to change the FourDigitCardFormatWatch to the following format 55555 5555 555 55.

How can i determine after 5 numbers add a space, then after 4 digits add a space and after 3 digits add a space.

Actual result: 4444 4444 4444

Expected result: 44444 4444 444


Answer:

Edit the class like this..

public class FourDigitCardFormatWatcher implements TextWatcher {

// Change this to what you want... ' ', '-' etc..
private final String char = " ";
EditText et_filed;


public FourDigitCardFormatWatcher(EditText et_filed){
    this.et_filed = et_filed;
}

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

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

@Override
public void afterTextChanged(Editable s) {
    String initial = s.toString();
    // remove all non-digits characters
    String processed = initial.replaceAll("\\D", "");

    // insert a space after all groups of 4 digits that are followed by another digit
    processed = processed.replaceAll("(\\d{5})(\\d{4})(\\d{3})(?=\\d)(?=\\d)(?=\\d)", "$1 $2 $3 ");

    //Remove the listener
    et_filed.removeTextChangedListener(this);

    //Assign processed text
    et_filed.setText(processed);

    try {
        et_filed.setSelection(processed.length());
    } catch (Exception e) {
        // TODO: handle exception
    }

    //Give back the listener
    et_filed.addTextChangedListener(this);
}
}

To add the listener

editText1.addTextChangedListener(new FourDigitCardFormatWatcher(editText1));