I want to create an Eddittext to type in currency values with 2 decimals from left to right. If there´s no value it shows 0.00, and as the user types the text should change acording to these rules:
I´ve tried getting it done using TextWatcher like in a similar question but I couldnt get it done as it kept calling TextWatcher after updating the text.
I finally got it working just as I wanted using a TextWatcher with this code, hope it helps someone:
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if ((count - before) > 0) {
String text = s.toString().replace(',', '.');
text = text.replace("..", ".");
if (text.equals(".")) {
text = "0,00";
amount_field.setText(text);
amount_field.setSelection(2);
} else {
int counter = 0;
for (int i = 0; i < text.length(); i++) {
if (text.charAt(i) == '.') {
counter++;
if (counter > 1) {
break;
}
}
}
if (counter > 1) {
StringBuilder sb = new StringBuilder(text);
sb.deleteCharAt(start);
amount_field.setText(sb.toString().replace('.', ','));
amount_field.setSelection(start);
} else {
Float value = Float.valueOf(text);
String result = String.format("%.2f", value);
amount_field.setText(result.replace('.', ','));
if (start != result.length()) {
amount_field.setSelection(start + 1);
} else {
amount_field.setSelection(start);
}
}
}
}
}
Try this:
String yourStringToPutIntoTextView = String.format("%.2f", YourFloat);
Here an example:
List<Float> listTestValue = new ArrayList<Float>();
listTestValue.add(new Float(10));
listTestValue.add(new Float(10.10));
listTestValue.add(new Float(1010));
listTestValue.add(new Float(0));
listTestValue.add(new Float(0.9));
listTestValue.add(new Float(.12));
listTestValue.add(new Float(0.01));
for(Float f : listTestValue)
{
String s = String.format("%.2f", f);
System.out.println(s);
}
If you have noInput format string with f = 0, like this:
String noInput = String.format("%.2f", (float)0);
Note that the values must be Float!
Output:
10,00
10,10
1010,00
0,00
0,90
0,12
0,01
Related
i have simple Edittext and when I'm going to change input letters in im setting listener new textWatcher and it's onTextChanged() method like:
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Log.d("qwer", "onTextChanged: " + s + " " + start + " " + before + " " + count);
String originalText = s.toString();
int originalTextLength = originalText.length();
int currentSelection = textHeading.getSelectionStart();
StringBuilder sb = new StringBuilder();
boolean hasChanged = false;
for (int i = 0; i < originalTextLength; i++) {
char currentChar = originalText.charAt(i);
if (isAllowed(currentChar) && i < 21) {
sb.append(currentChar);
} else {
hasChanged = true;
textHeading.setError("Please insert current letters");
}
}
if (hasChanged) {
String newText = sb.toString();
textHeading.setText(capitalize(newText));
textHeading.setSelection(currentSelection);
}
}
endless cycle begins when i'm setting validated data back to the edittext becouse it calls method ontextCahnged() again. so my goal is dynamically change input letters and i have to capitalize it. I know there is more the easiest way to do it. but i need to do by this way.
You problem is with TextWatcher not with the logic what you are writing. Below Code block is causing the issue (endless cycle begins when i'm setting validated data back to the edittext becouse it calls method ontextCahnged() again)
if (hasChanged) {
String newText = sb.toString();
textHeading.setText(capitalize(newText)); // <<<<<< This line is culprit which is calling Watcher's method again and again.
textHeading.setSelection(currentSelection);
}
To handle this issue, you need to do below steps
Remove Watcher from EditText
Set text
Add Watcher to EditText.
For more information read How can I change the EditText text without triggering the Text Watcher?
There is many ways to do that:
1- Using common Utils
Library: http://commons.apache.org/proper/commons-lang/
StringUtils.capitalize(..)
2- By Custom method
public static String upperCaseFirst(String value) {
// Convert String to char array.
char[] array = value.toCharArray();
// Modify first element in array.
array[0] = Character.toUpperCase(array[0]);
// Return string.
return new String(array);
}
3- From apache Common
Library: http://commons.apache.org/proper/commons-lang/
WordUtils.capitalize(java.lang.String)
Now you can assign that string to your input box.
You can set the input type (of EditText) to TYPE_CLASS_TEXT | TYPE_TEXT_FLAG_CAP_CHARACTERS.
OR
Set android:inputType="textCapSentences" on your EditText.
You can follow this link https://developer.android.com/reference/android/text/InputFilter.AllCaps
You can use following InputFilter.AllCaps
or this
android:inputType="textCapCharacters"
Why not use a flag ? I've modified your code by adding a boolean setManually flag.
boolean setManually = false;
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Log.d("qwer", "onTextChanged: " + s + " " + start + " " + before + " " + count);
if (setManually) {
setManually = false;
return;
}
String originalText = s.toString();
int originalTextLength = originalText.length();
int currentSelection = textHeading.getSelectionStart();
StringBuilder sb = new StringBuilder();
boolean hasChanged = false;
for (int i = 0; i < originalTextLength; i++) {
char currentChar = originalText.charAt(i);
if (isAllowed(currentChar) && i < 21) {
sb.append(currentChar);
} else {
hasChanged = true;
textHeading.setError("Please insert current letters");
}
}
if (hasChanged) {
String newText = sb.toString();
setManually = true;
textHeading.setText(capitalize(newText));
textHeading.setSelection(currentSelection);
}
}
You can just simply use in XML
android:inputType="textCapCharacters"
no need to write code for capitlize letter.
Try like this:
String originalText = s.toString().toUpperCase();
or
if (hasChanged) {
String newText = sb.toString().toUpperCase();
textHeading.setText(newText);
textHeading.setSelection(currentSelection);
}
I want to show my numbers in money format and separate digits like the example below:
1000 -----> 1,000
10000 -----> 10,000
100000 -----> 100,000
1000000 -----> 1,000,000
Thanks
Another approach :
NumberFormat format = NumberFormat.getCurrencyInstance();
format.setMaximumFractionDigits(0);
format.setCurrency(Currency.getInstance("EUR"));
format.format(1000000);
This way, it's displaying 1 000 000 € or 1,000,000 €, depending on device currency's display settings
You need to use a number formatter, like so:
NumberFormat formatter = new DecimalFormat("#,###");
double myNumber = 1000000;
String formattedNumber = formatter.format(myNumber);
//formattedNumber is equal to 1,000,000
Hope this helps!
double number = 1000000000.0;
String COUNTRY = "US";
String LANGUAGE = "en";
String str = NumberFormat.getCurrencyInstance(new Locale(LANGUAGE, COUNTRY)).format(number);
//str = $1,000,000,000.00
Currency formatter.
public static String currencyFormat(String amount) {
DecimalFormat formatter = new DecimalFormat("###,###,##0.00");
return formatter.format(Double.parseDouble(amount));
}
Use this:
int number = 1000000000;
String str = NumberFormat.getNumberInstance(Locale.US).format(number);
//str = 1,000,000,000
This Method gives you the exact output which you need:
public String currencyFormatter(String num) {
double m = Double.parseDouble(num);
DecimalFormat formatter = new DecimalFormat("###,###,###");
return formatter.format(m);
}
Try the following solution:
NumberFormat format = NumberFormat.getCurrencyInstance();
((TextView)findViewById(R.id.text_result)).setText(format.format(result));
The class will return a formatter for the device default currency.
You can refer to this link for more information:
https://developer.android.com/reference/java/text/NumberFormat.html
Here's a kotlin Extension that converts a Double to a Currency(Nigerian Naira)
fun Double.toRidePrice():String{
val format: NumberFormat = NumberFormat.getCurrencyInstance()
format.maximumFractionDigits = 0
format.currency = Currency.getInstance("NGN")
return format.format(this.roundToInt())
}
Use a Formatter class
For eg:
String s = (String.format("%,d", 1000000)).replace(',', ' ');
Look into:
http://developer.android.com/reference/java/util/Formatter.html
The way that I do this in our app is this:
amount.addTextChangedListener(new CurrencyTextWatcher(amount));
And the CurrencyTextWatcher is this:
public class CurrencyTextWatcher implements TextWatcher {
private EditText ed;
private String lastText;
private boolean bDel = false;
private boolean bInsert = false;
private int pos;
public CurrencyTextWatcher(EditText ed) {
this.ed = ed;
}
public static String getStringWithSeparator(long value) {
DecimalFormat formatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US);
String f = formatter.format(value);
return f;
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
bDel = false;
bInsert = false;
if (before == 1 && count == 0) {
bDel = true;
pos = start;
} else if (before == 0 && count == 1) {
bInsert = true;
pos = start;
}
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
lastText = s.toString();
}
#Override
public void afterTextChanged(Editable s) {
ed.removeTextChangedListener(this);
StringBuilder sb = new StringBuilder();
String text = s.toString();
for (int i = 0; i < text.length(); i++) {
if ((text.charAt(i) >= 0x30 && text.charAt(i) <= 0x39) || text.charAt(i) == '.' || text.charAt(i) == ',')
sb.append(text.charAt(i));
}
if (!sb.toString().equals(s.toString())) {
bDel = bInsert = false;
}
String newText = getFormattedString(sb.toString());
s.clear();
s.append(newText);
ed.addTextChangedListener(this);
if (bDel) {
int idx = pos;
if (lastText.length() - 1 > newText.length())
idx--; // if one , is removed
if (idx < 0)
idx = 0;
ed.setSelection(idx);
} else if (bInsert) {
int idx = pos + 1;
if (lastText.length() + 1 < newText.length())
idx++; // if one , is added
if (idx > newText.length())
idx = newText.length();
ed.setSelection(idx);
}
}
private String getFormattedString(String text) {
String res = "";
try {
String temp = text.replace(",", "");
long part1;
String part2 = "";
int dotIndex = temp.indexOf(".");
if (dotIndex >= 0) {
part1 = Long.parseLong(temp.substring(0, dotIndex));
if (dotIndex + 1 <= temp.length()) {
part2 = temp.substring(dotIndex + 1).trim().replace(".", "").replace(",", "");
}
} else
part1 = Long.parseLong(temp);
res = getStringWithSeparator(part1);
if (part2.length() > 0)
res += "." + part2;
else if (dotIndex >= 0)
res += ".";
} catch (Exception ex) {
ex.printStackTrace();
}
return res;
}
Now if you add this watcher to your EditText, as soon as user enter his number, the watcher decides whether it needs separator or not.
i used this code for my project and it works:
EditText edt_account_amount = findViewById(R.id.edt_account_amount);
edt_account_amount.addTextChangedListener(new DigitFormatWatcher(edt_account_amount));
and defined class:
public class NDigitCardFormatWatcher implements TextWatcher {
EditText et_filed;
String processed = "";
public NDigitCardFormatWatcher(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 editable) {
String initial = editable.toString();
if (et_filed == null) return;
if (initial.isEmpty()) return;
String cleanString = initial.replace(",", "");
NumberFormat formatter = new DecimalFormat("#,###");
double myNumber = new Double(cleanString);
processed = formatter.format(myNumber);
//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);
}
}
Updated 2022 answer
Try this snippet. It formats a number in string complete with the currency & setting fractional digits.
Upvote if this helped you! :)
/**
* Formats amount in string to human-readable amount (separated with commas
* & prepends currency symbol)
*
* #param amount The amount to format in String
* #return The formatted amount complete with separators & currency symbol added
*/
public static String formatCurrency(String amount) {
String formattedAmount = amount;
try {
if (amount == null || amount.isEmpty())
throw new Exception("Amount is null/empty");
Double amountInDouble = Double.parseDouble(amount);
NumberFormat numberFormat = NumberFormat.getCurrencyInstance(new Locale("en", "IN"));
numberFormat.setMaximumFractionDigits(2);
numberFormat.setMinimumFractionDigits(2);
formattedAmount = numberFormat.format(amountInDouble);
} catch (Exception exception) {
exception.printStackTrace();
return formattedAmount;
}
return formattedAmount;
}
private val currencyFormatter = NumberFormat.getCurrencyInstance(LOCALE_AUS).configure()
private fun NumberFormat.configure() = apply {
maximumFractionDigits = 2
minimumFractionDigits = 2
}
fun Number.asCurrency(): String {
return currencyFormatter.format(this)
}
And then just use as
val x = 100000.234
x.asCurrency()
If you have the value stored in a String like me, which was coming from the server like "$20000.00".
You can do something like this in Kotlin (JetpackCompose):
#Composable
fun PrizeAmount(
modifier: Modifier = Modifier,
prize: String,
)
{
val currencyFormat = NumberFormat.getCurrencyInstance(Locale("en", "US"))
val text = currencyFormat.format(prize.substringAfter("$").toDouble())
...
}
Output: "$20,000.00"
NumberFormat.getCurrencyInstance(Locale("ES", "es")).format(number)
here is a kotlin version to Format Currency, here i'm getting an argument from another fragment from an input Field then it will be set in the textView in the main Fragment
fun formatArgumentCurrency(argument : String, textView: TextView) {
val valueText = requireArguments().get(argument).toString()
val dec = DecimalFormat("#,###.##")
val number = java.lang.Double.valueOf(valueText)
val value = dec.format(number)
val currency = Currency.getInstance("USD")
val symbol = currency.symbol
textView.text = String.format("$symbol$value","%.2f" )
}
You can easily achieve this with this small simple library.
https://github.com/jpvs0101/Currencyfy
Just pass any number, then it will return formatted string, just like that.
currencyfy (500000.78); // $ 500,000.78 //default
currencyfy (500000.78, false); // $ 500,001 // hide fraction (will round off automatically!)
currencyfy (500000.78, false, false); // 500,001 // hide fraction & currency symbol
currencyfy (new Locale("en", "in"), 500000.78); // ₹ 5,00,000.78 // custom locale
It compatible with all versions of Android including older versions!
Can I ask how to format string value e.g. 5000000.00 to 5,000,000.00? Apparently I'm doing currency related stuff for android application, I can managed to just format string value 5000000 to 5,000,000 without the dot separator in the edit text. I would like to store the string value for later to be used to parseDouble so that I will need to calculate and have some decimals. I managed to do with just comma separator but any idea on how to make the dot to be shown in the edit text as well?
The following is my code:
amountText.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) {
amountText.removeTextChangedListener(this);
if(!amountText.getText().toString().equals(""))
{
try {
String editText = amountText.getText().toString();
String newStr = editText.replace("$", "").replace(",", "");
customer.getProperty().get(groupPosition).setAmount(newStr);
String formattedString = formatString(customer.getProperty().get(groupPosition).getAmount());
amountText.setText(formattedString);
amountText.setSelection(amountText.getText().length());
// to place the cursor at the end of text
} catch (NumberFormatException nfe) {
nfe.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
amountText.addTextChangedListener(this);
}
});
public String formatString(String s)
{
String givenstring = s.toString();
Long longval;
if (givenstring.contains(",")) {
givenstring = givenstring.replaceAll(",", "");
}
longval = Long.parseLong(givenstring);
DecimalFormat formatter = new DecimalFormat("#,###,###");
String formattedString = formatter.format(longval);
return formattedString;
}
I have tested use parseDouble but when I input "." in EditText, it just won't appear, and if I used long variable instead, it will give wrong format and error. (java.lang.NumberFormatException: Invalid long: "500000.00"). All values are done in string and later processing I will just parse the value when doing calculation.
Thank you and appreciate for anyone guidance and I apologize if there exists the post that is similar as I did not manage to find solution yet.
This is working & fully tested code just copy & paste it to try
TextWatcher amountTextWatcher = 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) {
int cursorPosition = etAmount.getSelectionEnd();
String originalStr = etAmount.getText().toString();
//To restrict only two digits after decimal place
etAmount.setFilters(new InputFilter[]{new MoneyValueFilter(Integer.parseInt(2))});
try {
etAmount.removeTextChangedListener(this);
String value = etAmount.getText().toString();
if (value != null && !value.equals("")) {
if (value.startsWith(".")) {
etAmount.setText("0.");
}
if (value.startsWith("0") && !value.startsWith("0.")) {
etAmount.setText("");
}
String str = etAmount.getText().toString().replaceAll(",", "");
if (!value.equals(""))
etAmount.setText(getDecimalFormattedString(str));
int diff = etAmount.getText().toString().length() - originalStr.length();
etAmount.setSelection(cursorPosition + diff);
}
etAmount.addTextChangedListener(this);
} catch (Exception ex) {
ex.printStackTrace();
etAmount.addTextChangedListener(this);
}
}
}
};
etAmount.addTextChangedListener(amountTextWatcher);
Here is method to add comma seperator to decimal number
/**
* Get decimal formated string to include comma seperator to decimal number
*
* #param value
* #return
*/
public static String getDecimalFormattedString(String value) {
if (value != null && !value.equalsIgnoreCase("")) {
StringTokenizer lst = new StringTokenizer(value, ".");
String str1 = value;
String str2 = "";
if (lst.countTokens() > 1) {
str1 = lst.nextToken();
str2 = lst.nextToken();
}
String str3 = "";
int i = 0;
int j = -1 + str1.length();
if (str1.charAt(-1 + str1.length()) == '.') {
j--;
str3 = ".";
}
for (int k = j; ; k--) {
if (k < 0) {
if (str2.length() > 0)
str3 = str3 + "." + str2;
return str3;
}
if (i == 3) {
str3 = "," + str3;
i = 0;
}
str3 = str1.charAt(k) + str3;
i++;
}
}
return "";
}
Method to restrict only two digits after decimal place in edittext
/**
* Restrict digits after decimal point value as per currency
*/
class MoneyValueFilter extends DigitsKeyListener {
private int digits;
public MoneyValueFilter(int i) {
super(false, true);
digits = i;
}
#Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
CharSequence out = super.filter(source, start, end, dest, dstart, dend);
// if changed, replace the source
if (out != null) {
source = out;
start = 0;
end = out.length();
}
int len = end - start;
// if deleting, source is empty
// and deleting can't break anything
if (len == 0) {
return source;
}
int dlen = dest.length();
// Find the position of the decimal .
for (int i = 0; i < dstart; i++) {
if (dest.charAt(i) == '.') {
// being here means, that a number has
// been inserted after the dot
// check if the amount of digits is right
return getDecimalFormattedString((dlen - (i + 1) + len > digits) ? "" : String.valueOf(new SpannableStringBuilder(source, start, end)));
}
}
for (int i = start; i < end; ++i) {
if (source.charAt(i) == '.') {
// being here means, dot has been inserted
// check if the amount of digits is right
if ((dlen - dend) + (end - (i + 1)) > digits)
return "";
else
break; // return new SpannableStringBuilder(source,
// start, end);
}
}
// if the dot is after the inserted part,
// nothing can break
return getDecimalFormattedString(String.valueOf(new SpannableStringBuilder(source, start, end)));
}
}
Try this:
public void afterTextChanged(Editable view) {
String s = null;
try {
// The comma in the format specifier does the trick
s = String.format("%,d", Long.parseLong(view.toString()));
} catch (NumberFormatException e) {
}
// Set s back to the view after temporarily removing the text change listener
}
Source: How to Automatically add thousand separators as number is input in EditText
I want to show the number in this xx-xxx-xxx-xxx-x format on EditText.
Eg (01-140-176-515-4)
I tried modifying the below code which displays the number in credit card number format
(xxxx-xxxx-xxxx-xxxx)
et_cardnumber.addTextChangedListener(new TextWatcher() {
private static final int TOTAL_SYMBOLS = 19; // size of pattern 0000-0000-0000-0000
private static final int TOTAL_DIGITS = 16; // max numbers of digits in pattern: 0000 x 4
private static final int DIVIDER_MODULO = 5; // means divider position is every 5th symbol beginning with 1
private static final int DIVIDER_POSITION = DIVIDER_MODULO - 1; // means divider position is every 4th symbol beginning with 0
private static final char DIVIDER = '-';
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// noop
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
iv_cardtype.setImageResource(getCreditCardTypeForImageView(et_cardnumber.getText().toString()));
}
#Override
public void afterTextChanged(Editable s) {
if (!isInputCorrect(s, TOTAL_SYMBOLS, DIVIDER_MODULO, DIVIDER)) {
s.replace(0, s.length(), buildCorrecntString(getDigitArray(s, TOTAL_DIGITS), DIVIDER_POSITION, DIVIDER));
}
}
private boolean isInputCorrect(Editable s, int totalSymbols, int dividerModulo, char divider) {
boolean isCorrect = s.length() <= totalSymbols; // check size of entered string
for (int i = 0; i < s.length(); i++) { // chech that every element is right
if (i > 0 && (i + 1) % dividerModulo == 0) {
isCorrect &= divider == s.charAt(i);
} else {
isCorrect &= Character.isDigit(s.charAt(i));
}
}
return isCorrect;
}
private String buildCorrecntString(char[] digits, int dividerPosition, char divider) {
final StringBuilder formatted = new StringBuilder();
for (int i = 0; i < digits.length; i++) {
if (digits[i] != 0) {
formatted.append(digits[i]);
if ((i > 0) && (i < (digits.length - 1)) && (((i + 1) % dividerPosition) == 0)) {
formatted.append(divider);
}
}
}
return formatted.toString();
}
private char[] getDigitArray(final Editable s, final int size) {
char[] digits = new char[size];
int index = 0;
for (int i = 0; i < s.length() && index < size; i++) {
char current = s.charAt(i);
if (Character.isDigit(current)) {
digits[index] = current;
index++;
}
}
return digits;
}
});
I couldn't get it right when i make changes to get the format which i want.
Can anyone help me to get the number in xx-xxx-xxx-xxx-x format?
i dont know much in Android , but try to build something like this .
str Yourstring = "";
for (int i = 0; i < digits.length; i++) {
if (i == 2 || i == 5 || i == 8 || i == 11) {
Yourstring = Yourstring + "-" +digits[i];
}
else
{
Yourstring = Yourstring +digits[i];
}
}
I answered this already in this link , please change the logic according to your format
Use this library.
it will allow according yo your formate
EditText Pattern lib
I have an Android EditText which when a user puts a number, it edits the number and adds thousand separators using Decimal Format, but when one is inputting floating point numbers, i does not add zeros after the decimal point. so i can not input 1.000000008 because the zeros won't go on but other numbers do.
Is there any java DecimalFormat pattern that will allow a user to input a zero after the decimal point?
Here's the code for my EditText.
am = new TextWatcher(){
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (s.toString().contains(String.valueOf(df.getDecimalFormatSymbols().getDecimalSeparator())))
{
hasFractionalPart = true;
} else {
hasFractionalPart = false;
}
}
public void afterTextChanged(Editable s) {
amount.removeTextChangedListener(this);
amount2.setText(s.toString());
try {
int inilen, endlen;
inilen = amount.getText().length();
String v = s.toString().replace(String.valueOf(df.getDecimalFormatSymbols().getGroupingSeparator()), "");
Number n = df.parse(v);
value = Double.parseDouble(v);
int cp = amount.getSelectionStart();
if (hasFractionalPart) {
amount.setText(df.format(n));
} else {
amount.setText(dfnd.format(n));
}
endlen = amount.getText().length();
int sel = (cp + (endlen - inilen));
if (sel > 0 && sel <= amount.getText().length()) {
amount.setSelection(sel);
} else {
// place cursor at the end?
amount.setSelection(amount.getText().length() - 1);
}
} catch (NumberFormatException nfe) {
// do nothing?
} catch (ParseException e) {
// do nothing?
}
amount.addTextChangedListener(this);
}
};
Rewrite
First, when a decimal symbol is present let's count how many zeros will be trimmed off by the formatter. (If we find a non-zero character after the decimal, we'll reset our count. For example 1.00200 only has two trailing zeros.) In onTextChanged():
int index = s.toString().indexOf(String.valueOf(df.getDecimalFormatSymbols().getDecimalSeparator()));
trailingZeroCount = 0;
if (index > -1)
{
for (index++; index < s.length(); index++) {
if (s.charAt(index) == '0')
trailingZeroCount++;
else {
trailingZeroCount = 0;
}
}
hasFractionalPart = true;
} else {
hasFractionalPart = false;
}
Next, append the appropriate number of zero's back on to the formatted String. In afterTextChanged():
if (hasFractionalPart) {
StringBuilder trailingZeros = new StringBuilder();
while (trailingZeroCount-- > 0)
trailingZeros.append('0');
amount.setText(df.format(n) + trailingZeros.toString());
} else {
amount.setText(dfnd.format(n));
}
Note: You haven't posted the formats you use, so I've had to make a few assumptions, but this is easily adaptable.