All-
I have a TextWatcher
that formats an EditText
to currency format:
private String current = "";
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(!s.toString().equals(current)){
editText$.removeTextChangedListener(this);
String cleanString = s.toString().replaceAll("[$,.]", "");
double parsed = Double.parseDouble(cleanString);
String formated = NumberFormat.getCurrencyInstance().format((parsed/100));
current = formated;
editText$.setText(formated);
editText$.setSelection(formated.length());
editText$.addTextChangedListener(this);
}
}
This works great, the problem is that my EditText
only needs whole numbers so I do not the user to be able to enter cents. So instead of 0.01 than 0.12 than 1.23 than 12.34, I want 1 than 12 than 123 than 1,234. How can I get rid of the decimal point but keep the commas? Thank you.
If you don't mind removing the period and trailing zeroes, you could do this:
mEditText.addTextChangedListener(new TextWatcher() {
private String current = "";
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (!s.toString().equals(current)) {
annualIncomeEntry.removeTextChangedListener(this);
String cleanString = s.toString().replaceAll("[$,]", "");
if (cleanString.length() > 0) {
double parsed = Double.parseDouble(cleanString);
NumberFormat formatter = NumberFormat.getCurrencyInstance();
formatter.setMaximumFractionDigits(0);
current = formatter.format(parsed);
} else {
current = cleanString;
}
annualIncomeEntry.setText(current);
annualIncomeEntry.setSelection(current.length());
annualIncomeEntry.addTextChangedListener(this);
}
}
@Override
public void afterTextChanged(Editable s) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
});
This will set the number formatter's maximum fraction digits to zero, removing all trailing zeroes and the period. I also removed the division by 100 so that all entered numbers are integers.
Also make sure that your EditText's inputType is "number" or this will crash if the user tries to enter a non-numeric character.
Hexar's answer was useful but it lacked error detection when the user deleted all the numbers or moved the cursor. I built on to his answer and an answer here to form a complete solution. It may not be best practice due to setting the EditText in the onTextChanged() method but it works.
/* don't allow user to move cursor while entering price */
mEditText.setMovementMethod(null);
mEditText.addTextChangedListener(new TextWatcher() {
private String current = "";
NumberFormat formatter = NumberFormat.getCurrencyInstance();
private double parsed;
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (!s.toString().equals(current)) {
/* remove listener to prevent stack overflow from infinite loop */
mEditText.removeTextChangedListener(this);
String cleanString = s.toString().replaceAll("[$,]", "");
try {
parsed = Double.parseDouble(cleanString);
}
catch(java.lang.NumberFormatException e) {
parsed = 0;
}
formatter.setMaximumFractionDigits(0);
String formatted = formatter.format(parsed);
current = formatted;
mEditText.setText(formatted);
/* add listener back */
mEditText.addTextChangedListener(this);
/* print a toast when limit is reached... see xml below.
* this is for 6 chars */
if (start == 7) {
Toast toast = Toast.makeText(getApplicationContext(),
"Maximum Limit Reached", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
}
}
A quick way to ensure the user doesn't enter invalid information is to edit the xml. For my program, a limit of 6 number characters was set.
<!-- it says maxLength 8 but it's really 6 digits and a '$' and a ',' -->
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="number|textVisiblePassword"
android:maxLength="8"
android:digits="0123456789"
android:id="@+id/mEditText"
android:hint="Price"/>
Why don't you format the amount using currencyFormat and then take out the .00 from the String.
private static final ThreadLocal<NumberFormat> currencyFormat = new ThreadLocal<NumberFormat>() {
@Override
protected NumberFormat initialValue() {
return NumberFormat.getCurrencyInstance();
}
};
currencyFormat.get().format( < your_amount_here > )
etProductCost.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) {
if (s.toString().length() == 1){
//first number inserted.
if (s.toString().equals(getString(R.string.currency_symbol))){
//if it is a currecy symbol
etProductCost.setText("");
}else {
etProductCost.setText(getString(R.string.currency_symbol) + s.toString());
etProductCost.setSelection(s.toString().length());
}
return;
}
//set cursor position to last in edittext
etProductCost.setSelection(s.toString().length());
}
@Override
public void afterTextChanged(Editable s) {}
});