Cómo agregar automáticamente mil separadores a medida que se ingresa el número en EditText

Im creando una aplicación de convertidor, quiero configurar EditText para que cuando el usuario ingresa el número a convertir, se agregue automáticamente un mil separador (,) en tiempo real al número una vez que se incremente en 3 figuras …. .thousand, million, billion, etc. y cuando se borre a menos de 4 cifras, el número vuelve a la normalidad. ¿Alguna ayuda? Gracias.

Puede utilizar String.format() en un TextWatcher . La coma en el especificador de formato hace el truco.

Esto no funciona para la entrada de coma flotante. Y tenga cuidado de no establecer un bucle infinito con el TextWatcher.

 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 } 

Resuelto el problema finalmente

Incluso, aunque es demasiado tarde, responde. Investigué mucho para lograr la tarea Para obtener el resultado correcto pero no pude. Así que finalmente resolví el problema que estábamos buscando y proporcioné esta respuesta a los buscadores de Google para guardar sus tiempos de búsqueda.

Fetures de los siguientes códigos

  1. Coloca el separador de miles en EditText medida que cambia el texto.

  2. agrega 0. Automáticamente cuando se presiona el punto (.) Al principio.

  3. Ignora 0 entrada al principio.

Solo copie la siguiente clase llamada

NumberTextWatcherForThousand que implementa TextWatcher

 import android.text.Editable; import android.text.TextWatcher; import android.widget.EditText; import java.util.StringTokenizer; /** * Created by skb on 12/14/2015. */ public class NumberTextWatcherForThousand implements TextWatcher { EditText editText; public NumberTextWatcherForThousand(EditText editText) { this.editText = editText; } @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 { editText.removeTextChangedListener(this); String value = editText.getText().toString(); if (value != null && !value.equals("")) { if(value.startsWith(".")){ editText.setText("0."); } if(value.startsWith("0") && !value.startsWith("0.")){ editText.setText(""); } String str = editText.getText().toString().replaceAll(",", ""); if (!value.equals("")) editText.setText(getDecimalFormattedString(str)); editText.setSelection(editText.getText().toString().length()); } editText.addTextChangedListener(this); return; } catch (Exception ex) { ex.printStackTrace(); editText.addTextChangedListener(this); } } public static String getDecimalFormattedString(String value) { 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++; } } public static String trimCommaOfString(String string) { // String returnString; if(string.contains(",")){ return string.replace(",","");} else { return string; } } } 

Use esta clase en su EditText siguiente manera

 editText.addTextChangedListener(new NumberTextWatcherForThousand(editText)); 

Para obtener la entrada como texto doble simple

Usa el método trimCommaOfString de la misma clase como este

 NumberTextWatcherForThousand.trimCommaOfString(editText.getText().toString()) 

Git

  public static String doubleToStringNoDecimal(double d) { DecimalFormat formatter = (DecimalFormat) NumberFormat.getInstance(Locale.US);; formatter .applyPattern("#,###"); return formatter.format(d); } 

Esta aplicación de muestra deconstruye los números de formateo con claridad.

Para resumir el enlace anterior, use un TextWatcher y en el método afterTextChanged() formatee la vista EditText con la siguiente lógica:

 @Override public void afterTextChanged(Editable s) { editText.removeTextChangedListener(this); try { String originalString = s.toString(); Long longval; if (originalString.contains(",")) { originalString = originalString.replaceAll(",", ""); } longval = Long.parseLong(originalString); DecimalFormat formatter = (DecimalFormat) NumberFormat.getInstance(Locale.US); formatter.applyPattern("#,###,###,###"); String formattedString = formatter.format(longval); //setting text after format to EditText editText.setText(formattedString); editText.setSelection(editText.getText().length()); } catch (NumberFormatException nfe) { nfe.printStackTrace(); } editText.addTextChangedListener(this); } 

Esta solución tiene alguna ventaja sobre otras respuestas. Por ejemplo, mantiene la posición del cursor del usuario incluso si edita el principio o el medio del número. Otras soluciones siempre saltan el cursor al final del número . Maneja decimales y números enteros , así como también configuraciones regionales que usan caracteres distintos de . para el separador decimal y , para el separador de miles de agrupaciones.

 class SeparateThousands(val groupingSeparator: String, val decimalSeparator: String) : TextWatcher { private var busy = false override fun afterTextChanged(s: Editable?) { if (s != null && !busy) { busy = true var place = 0 val decimalPointIndex = s.indexOf(decimalSeparator) var i = if (decimalPointIndex == -1) { s.length - 1 } else { decimalPointIndex - 1 } while (i >= 0) { val c = s[i] if (c == ',') { s.delete(i, i + 1) } else { if (place % 3 == 0 && place != 0) { // insert a comma to the left of every 3rd digit (counting from right to // left) unless it's the leftmost digit s.insert(i + 1, groupingSeparator) } place++ } i-- } busy = false } } override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { } override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { } } 

Luego en xml:

   

Y finalmente registra al observador:

 findViewById(R.id.myNumberField).addTextChangedListener( SeparateThousands(groupingSeparator, decimalSeparator)) 

Manejar . vs, en diferentes configuraciones regionales usa groupingSeparator y decimalSeparator, que pueden provenir de DecimalFormatSymbols o cadenas localizadas.

Puedes usar este código de muchas formas en tu progtwig, le das una cadena y separa cada tres de la derecha y colocas el espacio allí.

 private String Spacer(String number){ StringBuilder strB = new StringBuilder(); strB.append(number); int Three = 0; for(int i=number.length();i>0;i--){ Three++; if(Three == 3){ strB.insert(i-1, " "); Three = 0; } } return strB.toString(); }// end Spacer() 

Puedes cambiarlo un poco y usarlo en textchangelistener. buena suerte

Aquí está mi clase ThousandNumberEditText

 public class ThousandNumberEditText extends android.support.v7.widget.AppCompatEditText { // TODO: 14/09/2017 change it if you want private static final int MAX_LENGTH = 20; private static final int MAX_DECIMAL = 3; public ThousandNumberEditText(Context context) { this(context, null); } public ThousandNumberEditText(Context context, AttributeSet attrs) { this(context, attrs, android.support.v7.appcompat.R.attr.editTextStyle); } public ThousandNumberEditText(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { addTextChangedListener(new ThousandNumberTextWatcher(this)); setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL); setFilters(new InputFilter[] { new InputFilter.LengthFilter(MAX_LENGTH) }); setHint("0"); // TODO: 14/09/2017 change it if you want } private static class ThousandNumberTextWatcher implements TextWatcher { private EditText mEditText; ThousandNumberTextWatcher(EditText editText) { mEditText = editText; } @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void afterTextChanged(Editable editable) { String originalString = editable.toString(); String cleanString = originalString.replaceAll("[,]", ""); if (cleanString.isEmpty()) { return; } String formattedString = getFormatString(cleanString); mEditText.removeTextChangedListener(this); mEditText.setText(formattedString); mEditText.setSelection(mEditText.getText().length()); mEditText.addTextChangedListener(this); } /** * Return the format string */ private String getFormatString(String cleanString) { if (cleanString.contains(".")) { return formatDecimal(cleanString); } else { return formatInteger(cleanString); } } private String formatInteger(String str) { BigDecimal parsed = new BigDecimal(str); DecimalFormat formatter; formatter = new DecimalFormat("#,###"); return formatter.format(parsed); } private String formatDecimal(String str) { if (str.equals(".")) { return "."; } BigDecimal parsed = new BigDecimal(str); DecimalFormat formatter; formatter = new DecimalFormat("#,###." + getDecimalPattern(str)); //example patter #,###.00 return formatter.format(parsed); } /** * It will return suitable pattern for format decimal * For example: 10.2 -> return 0 | 10.23 -> return 00 | 10.235 -> return 000 */ private String getDecimalPattern(String str) { int decimalCount = str.length() - 1 - str.indexOf("."); StringBuilder decimalPattern = new StringBuilder(); for (int i = 0; i < decimalCount && i < MAX_DECIMAL; i++) { decimalPattern.append("0"); } return decimalPattern.toString(); } } } 

Utilizando

 <.ThousandNumberEditText android:layout_width="match_parent" android:layout_height="wrap_content" /> 

Sé que llego muy tarde a la fiesta, pero puede ser muy útil para futuros usuarios. Mi respuesta es una extensión de la respuesta de Shree Krishna .

Mejoras:

  1. Los miles de separadores y marcadores decimales son locales, es decir, se usan de acuerdo con la configuración Locale del dispositivo.
  2. La posición del cursor no cambia después de eliminar o agregar elementos en el medio también (en su cursor de respuesta se restableció al final).
  3. La calidad general del código se ha mejorado especialmente el método getDecimalFormattedString .

Código:

  import android.text.Editable; import android.text.TextWatcher; import android.widget.EditText; import java.text.DecimalFormat; /** * Created by srv_twry on 4/12/17. * Source: https://stackoverflow.com/a/34265406/137744 * The custom TextWatcher that automatically adds thousand separators in EditText. */ public class ThousandSeparatorTextWatcher implements TextWatcher { private DecimalFormat df; private EditText editText; private static String thousandSeparator; private static String decimalMarker; private int cursorPosition; public ThousandSeparatorTextWatcher(EditText editText) { this.editText = editText; df = new DecimalFormat("#,###.##"); df.setDecimalSeparatorAlwaysShown(true); thousandSeparator = Character.toString(df.getDecimalFormatSymbols().getGroupingSeparator()); decimalMarker = Character.toString(df.getDecimalFormatSymbols().getDecimalSeparator()); } @Override public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) { cursorPosition = editText.getText().toString().length() - editText.getSelectionStart(); } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {} @Override public void afterTextChanged(Editable s) { try { editText.removeTextChangedListener(this); String value = editText.getText().toString(); if (value != null && !value.equals("")) { if (value.startsWith(decimalMarker)) { String text = "0" + decimalMarker; editText.setText(text); } if (value.startsWith("0") && !value.startsWith("0" + decimalMarker)) { int index = 0; while (index < value.length() && value.charAt(index) == '0') { index++; } String newValue = Character.toString(value.charAt(0)); if (index != 0) { newValue = value.charAt(0) + value.substring(index); } editText.setText(newValue); } String str = editText.getText().toString().replaceAll(thousandSeparator, ""); if (!value.equals("")) { editText.setText(getDecimalFormattedString(str)); } editText.setSelection(editText.getText().toString().length()); } //setting the cursor back to where it was editText.setSelection(editText.getText().toString().length() - cursorPosition); editText.addTextChangedListener(this); } catch (Exception ex) { ex.printStackTrace(); editText.addTextChangedListener(this); } } private static String getDecimalFormattedString(String value) { String[] splitValue = value.split("\\."); String beforeDecimal = value; String afterDecimal = null; String finalResult = ""; if (splitValue.length == 2) { beforeDecimal = splitValue[0]; afterDecimal = splitValue[1]; } int count = 0; for (int i = beforeDecimal.length() - 1; i >= 0 ; i--) { finalResult = beforeDecimal.charAt(i) + finalResult; count++; if (count == 3 && i > 0) { finalResult = thousandSeparator + finalResult; count = 0; } } if (afterDecimal != null) { finalResult = finalResult + decimalMarker + afterDecimal; } return finalResult; } /* * Returns the string after removing all the thousands separators. * */ public static String getOriginalString(String string) { return string.replace(thousandSeparator,""); } } 

Como tenía el mismo problema, decidí encontrar una solución.

Encuentra mi función a continuación espero que ayude a las personas a encontrar una solución

 securityDeposit.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // TODO Auto-generated method stub } @Override public void beforeTextChanged(CharSequence s, int start, int before, int count) { // TODO Auto-generated method stub } @Override public void afterTextChanged(Editable s) { // TODO Auto-generated method stub if (s.toString().trim().length() > 0) { int rentValue = Integer.parseInt(s.toString() .replaceAll(",", "")); StringBuffer rentVal = new StringBuffer(); if (rentValue > 10000000) { s.clear(); s.append("10,000,000"); } else { if (s.length() == 4) { char x[] = s.toString().toCharArray(); char y[] = new char[x.length + 1]; for (int z = 0; z < y.length; z++) { if (z == 1) { y[1] = ','; } else { if (z == 0) y[z] = x[z]; else { y[z] = x[z - 1]; } } } for (int z = 0; z < y.length; z++) { rentVal = rentVal.append(y[z]); } s.clear(); s.append(rentVal); } } } } });