Limite los espacios decimales en Android EditText

Intento escribir una aplicación que te ayude a administrar tus finanzas. Estoy usando un campo EditText donde el usuario puede especificar una cantidad de dinero.

Configuré inputType en numberDecimal que funciona bien, excepto que esto permite a las personas ingresar números como 123.122 que no es perfecto para dinero.

¿Hay alguna forma de limitar el número de caracteres después del punto decimal a dos?

Una manera más elegante sería usar una expresión regular (regex) de la siguiente manera:

 public class DecimalDigitsInputFilter implements InputFilter { Pattern mPattern; public DecimalDigitsInputFilter(int digitsBeforeZero,int digitsAfterZero) { mPattern=Pattern.compile("[0-9]{0," + (digitsBeforeZero-1) + "}+((\\.[0-9]{0," + (digitsAfterZero-1) + "})?)||(\\.)?"); } @Override public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { Matcher matcher=mPattern.matcher(dest); if(!matcher.matches()) return ""; return null; } } 

Para usarlo hazlo:

 editText.setFilters(new InputFilter[] {new DecimalDigitsInputFilter(5,2)}); 

Solución más simple sin usar regex:

 import android.text.InputFilter; import android.text.Spanned; /** * Input filter that limits the number of decimal digits that are allowed to be * entered. */ public class DecimalDigitsInputFilter implements InputFilter { private final int decimalDigits; /** * Constructor. * * @param decimalDigits maximum decimal digits */ public DecimalDigitsInputFilter(int decimalDigits) { this.decimalDigits = decimalDigits; } @Override public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { int dotPos = -1; int len = dest.length(); for (int i = 0; i < len; i++) { char c = dest.charAt(i); if (c == '.' || c == ',') { dotPos = i; break; } } if (dotPos >= 0) { // protects against many dots if (source.equals(".") || source.equals(",")) { return ""; } // if the text is entered before the dot if (dend <= dotPos) { return null; } if (len - dotPos > decimalDigits) { return ""; } } return null; } } 

Usar:

 editText.setFilters(new InputFilter[] {new DecimalDigitsInputFilter(2)}); 

Esta implementación de InputFilter resuelve el problema.

 import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.method.DigitsKeyListener; public class MoneyValueFilter extends DigitsKeyListener { public MoneyValueFilter() { super(false, true); } private int digits = 2; public void setDigits(int d) { digits = d; } @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 (dlen-(i+1) + len > digits) ? "" : 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 new SpannableStringBuilder(source, start, end); } } 

Aquí hay un ejemplo de InputFilter que solo permite un máximo de 4 dígitos antes del punto decimal y un máximo de 1 dígito después de eso.

Valores que edittext permite: 555.2 , 555 , .2

Valores que editan bloques de texto: 55555.2 , 055.2 , 555.42

  InputFilter filter = new InputFilter() { final int maxDigitsBeforeDecimalPoint=4; final int maxDigitsAfterDecimalPoint=1; @Override public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { StringBuilder builder = new StringBuilder(dest); builder.replace(dstart, dend, source .subSequence(start, end).toString()); if (!builder.toString().matches( "(([1-9]{1})([0-9]{0,"+(maxDigitsBeforeDecimalPoint-1)+"})?)?(\\.[0-9]{0,"+maxDigitsAfterDecimalPoint+"})?" )) { if(source.length()==0) return dest.subSequence(dstart, dend); return ""; } return null; } }; mEdittext.setFilters(new InputFilter[] { filter }); 

TextWatcher esto con la ayuda de TextWatcher de la siguiente manera

 final EditText et = (EditText) findViewById(R.id.EditText1); et.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 = et.getText().toString(); et.setOnKeyListener(new 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); et.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()); et.setFilters(fArray); //prevent the edittext from accessing digits //by setting maximum length as total number of digits we typed till now. } count++; } } } }); 

Esta solución no permitirá al usuario ingresar más de dos dígitos después del punto decimal. También puede ingresar cualquier cantidad de dígitos antes del punto decimal. Consulte este blog http://v4all123.blogspot.com/2013/05/set-limit-for-fraction-in-decimal.html para establecer el filtro de EditText múltiple. Espero que esto sea de ayuda. Gracias.

Hice algunas correcciones para la solución @Pinhassi. Maneja algunos casos:

1. puedes mover el cursor a cualquier lugar

2.minus signo manejo

3.digitsbefore = 2 y digitsafter = 4 e ingrese 12.4545. Entonces, si quieres eliminar “.”, No permitirá.

 public class DecimalDigitsInputFilter implements InputFilter { private int mDigitsBeforeZero; private int mDigitsAfterZero; private Pattern mPattern; private static final int DIGITS_BEFORE_ZERO_DEFAULT = 100; private static final int DIGITS_AFTER_ZERO_DEFAULT = 100; public DecimalDigitsInputFilter(Integer digitsBeforeZero, Integer digitsAfterZero) { this.mDigitsBeforeZero = (digitsBeforeZero != null ? digitsBeforeZero : DIGITS_BEFORE_ZERO_DEFAULT); this.mDigitsAfterZero = (digitsAfterZero != null ? digitsAfterZero : DIGITS_AFTER_ZERO_DEFAULT); mPattern = Pattern.compile("-?[0-9]{0," + (mDigitsBeforeZero) + "}+((\\.[0-9]{0," + (mDigitsAfterZero) + "})?)||(\\.)?"); } @Override public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { String replacement = source.subSequence(start, end).toString(); String newVal = dest.subSequence(0, dstart).toString() + replacement + dest.subSequence(dend, dest.length()).toString(); Matcher matcher = mPattern.matcher(newVal); if (matcher.matches()) return null; if (TextUtils.isEmpty(source)) return dest.subSequence(dstart, dend); else return ""; } } 

Mi solución es simple y funciona perfecto!

 public class DecimalInputTextWatcher implements TextWatcher { private String mPreviousValue; private int mCursorPosition; private boolean mRestoringPreviousValueFlag; private int mDigitsAfterZero; private EditText mEditText; public DecimalInputTextWatcher(EditText editText, int digitsAfterZero) { mDigitsAfterZero = digitsAfterZero; mEditText = editText; mPreviousValue = ""; mRestoringPreviousValueFlag = false; } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { if (!mRestoringPreviousValueFlag) { mPreviousValue = s.toString(); mCursorPosition = mEditText.getSelectionStart(); } } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { if (!mRestoringPreviousValueFlag) { if (!isValid(s.toString())) { mRestoringPreviousValueFlag = true; restrePreviousValue(); } } else { mRestoringPreviousValueFlag = false; } } private void restrePreviousValue() { mEditText.setText(mPreviousValue); mEditText.setSelection(mCursorPosition); } private boolean isValid(String s) { Pattern patternWithDot = Pattern.compile("[0-9]*((\\.[0-9]{0," + mDigitsAfterZero + "})?)||(\\.)?"); Pattern patternWithComma = Pattern.compile("[0-9]*((,[0-9]{0," + mDigitsAfterZero + "})?)||(,)?"); Matcher matcherDot = patternWithDot.matcher(s); Matcher matcherComa = patternWithComma.matcher(s); return matcherDot.matches() || matcherComa.matches(); } } 

Uso:

 myTextEdit.addTextChangedListener(new DecimalInputTextWatcher(myTextEdit, 2)); 

No me gusta la otra solución y creé la mía. Con esta solución, no puedes ingresar más de MAX_BEFORE_POINT dígito antes del punto y los decimales no pueden ser más que MAX_DECIMAL.

¡No puedes escribir el dígito en exceso, no hay otros efectos! En adicional si escribe “.” escribe “0”

  1. Establezca EditText en el diseño para:

    android: inputType = “numberDecimal”

  2. Agregue el Listener en su onCreate. Si desea modificar el número de dígitos antes y después del punto, edite la llamada a PerfectDecimal (str, NUMBER_BEFORE_POINT, NUMBER_DECIMALS), aquí se establece en 3 y 2.

     EditText targetEditText = (EditText)findViewById(R.id.targetEditTextLayoutId); targetEditText.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) { String str = targetEditText.getText().toString(); if (str.isEmpty()) return; String str2 = PerfectDecimal(str, 3, 2); if (!str2.equals(str)) { targetEditText.setText(str2); int pos = targetEditText.getText().length(); targetEditText.setSelection(pos); } } }); 
  3. Incluye esta Funcion:

     public String PerfectDecimal(String str, int MAX_BEFORE_POINT, int MAX_DECIMAL){ if(str.charAt(0) == '.') str = "0"+str; int max = str.length(); String rFinal = ""; boolean after = false; int i = 0, up = 0, decimal = 0; char t; while(i < max){ t = str.charAt(i); if(t != '.' && after == false){ up++; if(up > MAX_BEFORE_POINT) return rFinal; }else if(t == '.'){ after = true; }else{ decimal++; if(decimal > MAX_DECIMAL) return rFinal; } rFinal = rFinal + t; i++; }return rFinal; } 

¡Y listo!

El InputFilter I se le ocurrió le permite configurar el número de dígitos antes y después de la posición decimal. Además, no permite ceros a la izquierda.

 public class DecimalDigitsInputFilter implements InputFilter { Pattern pattern; public DecimalDigitsInputFilter(int digitsBeforeDecimal, int digitsAfterDecimal) { pattern = Pattern.compile("(([1-9]{1}[0-9]{0," + (digitsBeforeDecimal - 1) + "})?||[0]{1})((\\.[0-9]{0," + digitsAfterDecimal + "})?)||(\\.)?"); } @Override public CharSequence filter(CharSequence source, int sourceStart, int sourceEnd, Spanned destination, int destinationStart, int destinationEnd) { // Remove the string out of destination that is to be replaced. String newString = destination.toString().substring(0, destinationStart) + destination.toString().substring(destinationEnd, destination.toString().length()); // Add the new string in. newString = newString.substring(0, destinationStart) + source.toString() + newString.substring(destinationStart, newString.length()); // Now check if the new string is valid. Matcher matcher = pattern.matcher(newString); if(matcher.matches()) { // Returning null indicates that the input is valid. return null; } // Returning the empty string indicates the input is invalid. return ""; } } // To use this InputFilter, attach it to your EditText like so: final EditText editText = (EditText) findViewById(R.id.editText); EditText.setFilters(new InputFilter[]{new DecimalDigitsInputFilter(4, 4)}); 

Intente utilizar NumberFormat.getCurrencyInstance () para formatear su cadena antes de ponerla en un TextView.

Algo como:

 NumberFormat currency = NumberFormat.getCurrencyInstance(); myTextView.setText(currency.format(dollars)); 

Editar – No hay inputType para la moneda que pude encontrar en los documentos. Me imagino que esto se debe a que hay algunas monedas que no siguen la misma regla para los decimales, como el yen japonés.

Como mencionó LeffelMania, puede corregir la entrada del usuario utilizando el código anterior con un TextWatcher que está configurado en su EditText .

Solución @Pinhassi ligeramente mejorada.

Funciona muy bien Valida cadenas concatenadas.

 public class DecimalDigitsInputFilter implements InputFilter { Pattern mPattern; public DecimalDigitsInputFilter() { mPattern = Pattern.compile("([1-9]{1}[0-9]{0,2}([0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)"); } @Override public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { String formatedSource = source.subSequence(start, end).toString(); String destPrefix = dest.subSequence(0, dstart).toString(); String destSuffix = dest.subSequence(dend, dest.length()).toString(); String result = destPrefix + formatedSource + destSuffix; result = result.replace(",", "."); Matcher matcher = mPattern.matcher(result); if (matcher.matches()) { return null; } return ""; } } 

El requisito es de 2 dígitos después de decimal. No debe haber límite para los dígitos antes del punto decimal. Entonces, la solución debería ser,

 public class DecimalDigitsInputFilter implements InputFilter { Pattern mPattern; public DecimalDigitsInputFilter() { mPattern = Pattern.compile("[0-9]*+((\\.[0-9]?)?)||(\\.)?"); } @Override public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { Matcher matcher = mPattern.matcher(dest); if (!matcher.matches()) return ""; return null; } } 

Y úsalo como,

 mEditText.setFilters(new InputFilter[]{new DecimalDigitsInputFilter()}); 

Gracias a @Pinhassi por la inspiración.

Todas las respuestas aquí son bastante complejas. Intenté simplificarlo. Mire mi código y decida por usted mismo:

 int temp = 0; int check = 0; editText.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if(editText.getText().toString().length() 

He modificado las soluciones anteriores y he creado el siguiente. Puede establecer el número de dígitos antes y después del punto decimal.

 public class DecimalDigitsInputFilter implements InputFilter { private final Pattern mPattern; public DecimalDigitsInputFilter(int digitsBeforeZero, int digitsAfterZero) { mPattern = Pattern.compile(String.format("[0-9]{0,%d}(\\.[0-9]{0,%d})?", digitsBeforeZero, digitsAfterZero)); } @Override public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { Matcher matcher = mPattern.matcher(createResultString(source, start, end, dest, dstart, dend)); if (!matcher.matches()) return ""; return null; } private String createResultString(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { String sourceString = source.toString(); String destString = dest.toString(); return destString.substring(0, dstart) + sourceString.substring(start, end) + destString.substring(dend); } 

}

 DecimalFormat form = new DecimalFormat("#.##", new DecimalFormatSymbols(Locale.US)); EditText et; et.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_DONE) { double a = Double.parseDouble(et.getText().toString()); et.setText(form.format(a)); } return false; } }); 

Lo que hace es que cuando sale de la fase de edición, formatea el campo con el formato correcto. En ese momento tiene solo 2 caracteres decimales. Creo que esta es una manera bastante fácil de hacer esto.

La clase Simple Helper está aquí para evitar que el usuario ingrese más de 2 dígitos después del decimal:

 public class CostFormatter implements TextWatcher { private final EditText costEditText; public CostFormatter(EditText costEditText) { this.costEditText = costEditText; } @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 synchronized void afterTextChanged(final Editable text) { String cost = text.toString().trim(); if(!cost.endsWith(".") && cost.contains(".")){ String numberBeforeDecimal = cost.split("\\.")[0]; String numberAfterDecimal = cost.split("\\.")[1]; if(numberAfterDecimal.length() > 2){ numberAfterDecimal = numberAfterDecimal.substring(0, 2); } cost = numberBeforeDecimal + "." + numberAfterDecimal; } costEditText.removeTextChangedListener(this); costEditText.setText(cost); costEditText.setSelection(costEditText.getText().toString().trim().length()); costEditText.addTextChangedListener(this); } } 

También he encontrado este problema. Quería poder reutilizar el código en muchos EditTexts. Esta es mi solución:

Uso:

 CurrencyFormat watcher = new CurrencyFormat(); priceEditText.addTextChangedListener(watcher); 

Clase:

 public static class CurrencyFormat implements TextWatcher { public void onTextChanged(CharSequence arg0, int start, int arg2,int arg3) {} public void beforeTextChanged(CharSequence arg0, int start,int arg2, int arg3) {} public void afterTextChanged(Editable arg0) { int length = arg0.length(); if(length>0){ if(nrOfDecimal(arg0.toString())>2) arg0.delete(length-1, length); } } private int nrOfDecimal(String nr){ int len = nr.length(); int pos = len; for(int i=0 ; i 

Realmente me gustó la respuesta de Pinhassi, pero noté que después de que el usuario ingresara los dígitos numéricos especificados después del punto decimal, ya no podía ingresar texto en el lado izquierdo del punto decimal. El problema era que la solución solo probaba el texto anterior que se había ingresado, no el texto actual que se ingresaba. Así que aquí está mi solución que inserta el nuevo personaje en el texto original para su validación.

 package com.test.test; import java.util.regex.Matcher; import java.util.regex.Pattern; import android.text.InputFilter; import android.text.Spanned; import android.util.Log; public class InputFilterCurrency implements InputFilter { Pattern moPattern; public InputFilterCurrency(int aiMinorUnits) { // http://www.regexplanet.com/advanced/java/index.html moPattern=Pattern.compile("[0-9]*+((\\.[0-9]{0,"+ aiMinorUnits + "})?)||(\\.)?"); } // InputFilterCurrency @Override public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { String lsStart = ""; String lsInsert = ""; String lsEnd = ""; String lsText = ""; Log.d("debug", moPattern.toString()); Log.d("debug", "source: " + source + ", start: " + start + ", end:" + end + ", dest: " + dest + ", dstart: " + dstart + ", dend: " + dend ); lsText = dest.toString(); // If the length is greater then 0, then insert the new character // into the original text for validation if (lsText.length() > 0) { lsStart = lsText.substring(0, dstart); Log.d("debug", "lsStart : " + lsStart); // Check to see if they have deleted a character if (source != "") { lsInsert = source.toString(); Log.d("debug", "lsInsert: " + lsInsert); } // if lsEnd = lsText.substring(dend); Log.d("debug", "lsEnd : " + lsEnd); lsText = lsStart + lsInsert + lsEnd; Log.d("debug", "lsText : " + lsText); } // if Matcher loMatcher = moPattern.matcher(lsText); Log.d("debug", "loMatcher.matches(): " + loMatcher.matches() + ", lsText: " + lsText); if(!loMatcher.matches()) { return ""; } return null; } // CharSequence } // InputFilterCurrency 

Y la llamada para establecer el filtro editText

 editText.setFilters(new InputFilter[] {new InputFilterCurrency(2)}); Ouput with two decimal places 05-22 15:25:33.434: D/debug(30524): [0-9]*+((\.[0-9]{0,2})?)||(\.)? 05-22 15:25:33.434: D/debug(30524): source: 5, start: 0, end:1, dest: 123.4, dstart: 5, dend: 5 05-22 15:25:33.434: D/debug(30524): lsStart : 123.4 05-22 15:25:33.434: D/debug(30524): lsInsert: 5 05-22 15:25:33.434: D/debug(30524): lsEnd : 05-22 15:25:33.434: D/debug(30524): lsText : 123.45 05-22 15:25:33.434: D/debug(30524): loMatcher.matches(): true, lsText: 123.45 Ouput inserting a 5 in the middle 05-22 15:26:17.624: D/debug(30524): [0-9]*+((\.[0-9]{0,2})?)||(\.)? 05-22 15:26:17.624: D/debug(30524): source: 5, start: 0, end:1, dest: 123.45, dstart: 2, dend: 2 05-22 15:26:17.624: D/debug(30524): lsStart : 12 05-22 15:26:17.624: D/debug(30524): lsInsert: 5 05-22 15:26:17.624: D/debug(30524): lsEnd : 3.45 05-22 15:26:17.624: D/debug(30524): lsText : 1253.45 05-22 15:26:17.624: D/debug(30524): loMatcher.matches(): true, lsText: 1253.45 

Mejoré la solución que usa una expresión regular de Pinhassi, por lo que también maneja las cajas de borde correctamente. Antes de verificar si la entrada es correcta, primero la cadena final se construye como se describe en los documentos de Android.

 public class DecimalDigitsInputFilter implements InputFilter { private Pattern mPattern; private static final Pattern mFormatPattern = Pattern.compile("\\d+\\.\\d+"); public DecimalDigitsInputFilter(int digitsBeforeDecimal, int digitsAfterDecimal) { mPattern = Pattern.compile( "^\\d{0," + digitsBeforeDecimal + "}([\\.,](\\d{0," + digitsAfterDecimal + "})?)?$"); } @Override public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { String newString = dest.toString().substring(0, dstart) + source.toString().substring(start, end) + dest.toString().substring(dend, dest.toString().length()); Matcher matcher = mPattern.matcher(newString); if (!matcher.matches()) { return ""; } return null; } } 

Uso:

 editText.setFilters(new InputFilter[] {new DecimalDigitsInputFilter(5,2)}); 

@Meh para ti …

 txtlist.setFilters(new InputFilter[] { new DigitsKeyListener( Boolean.FALSE,Boolean.TRUE) { int beforeDecimal = 7; int afterDecimal = 2; @Override public CharSequence filter(CharSequence source, int start, int end,Spanned dest, int dstart, int dend) { String etText = txtlist.getText().toString(); String temp = txtlist.getText() + source.toString(); if (temp.equals(".")) { return "0."; } else if (temp.toString().indexOf(".") == -1) { // no decimal point placed yet if (temp.length() > beforeDecimal) { return ""; } } else { int dotPosition ; int cursorPositon = txtlistprice.getSelectionStart(); if (etText.indexOf(".") == -1) { dotPosition = temp.indexOf("."); }else{ dotPosition = etText.indexOf("."); } if(cursorPositon <= dotPosition){ String beforeDot = etText.substring(0, dotPosition); if(beforeDot.length() afterDecimal) { return ""; } } } return super.filter(source, start, end, dest, dstart, dend); } } }); 

Una respuesta muy tardía: podemos hacerlo simplemente así:

 etv.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() > 3 && s.toString().contains(".")) { if (s.toString().length() - s.toString().indexOf(".") > 3) { etv.setText(s.toString().substring(0, s.length() - 1)); etv.setSelection(edtSendMoney.getText().length()); } } } @Override public void afterTextChanged(Editable arg0) { } } 

Como dijeron otros, agregué esta clase en mi proyecto y configuré el filtro para EditText que quiero.

El filtro se copia de la respuesta de @ Pixel. Solo estoy poniendo todo junto.

 public class DecimalDigitsInputFilter implements InputFilter { Pattern mPattern; public DecimalDigitsInputFilter() { mPattern = Pattern.compile("([1-9]{1}[0-9]{0,2}([0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)"); } @Override public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { String formatedSource = source.subSequence(start, end).toString(); String destPrefix = dest.subSequence(0, dstart).toString(); String destSuffix = dest.subSequence(dend, dest.length()).toString(); String result = destPrefix + formatedSource + destSuffix; result = result.replace(",", "."); Matcher matcher = mPattern.matcher(result); if (matcher.matches()) { return null; } return ""; } } 

Ahora configura el filtro en tu EditText así.

 mEditText.setFilters(new InputFilter[]{new DecimalDigitsInputFilter()}); 

Aquí una cosa importante es que resuelve mi problema de no permitir mostrar más de dos dígitos después del punto decimal en ese EditText pero el problema es cuando getText() desde ese EditText , devuelve toda la entrada que EditText .

Por ejemplo, después de aplicar el filtro sobre EditText , intenté establecer la entrada 1.5699856987. Entonces en la pantalla muestra 1.56 que es perfecto.

Luego quise usar esta entrada para algunos otros cálculos, así que quería obtener el texto de ese campo de entrada ( EditText ). Cuando llamé a mEditText.getText().toString() , devuelve 1.5699856987, que no era aceptable en mi caso.

Así que tuve que analizar el valor nuevamente después de obtenerlo desde EditText .

 BigDecimal amount = new BigDecimal(Double.parseDouble(mEditText.getText().toString().trim())) .setScale(2, RoundingMode.HALF_UP); 

setScale hace el truco aquí después de obtener el texto completo de EditText .

He cambiado la respuesta №6 (por Favas Kv) porque allí puedes poner simplemente el punto en la primera posición.

 final InputFilter [] filter = { new InputFilter() { @Override public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { StringBuilder builder = new StringBuilder(dest); builder.replace(dstart, dend, source .subSequence(start, end).toString()); if (!builder.toString().matches( "(([1-9]{1})([0-9]{0,4})?(\\.)?)?([0-9]{0,2})?" )) { if(source.length()==0) return dest.subSequence(dstart, dend); return ""; } return null; } }}; 

Aquí está mi solución:

  yourEditText.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { NumberFormat formatter = new DecimalFormat("#.##"); double doubleVal = Double.parseDouble(s.toString()); yourEditText.setText(formatter.format(doubleVal)); } @Override public void beforeTextChanged(CharSequence s, int start, int count,int after) {} @Override public void afterTextChanged(Editable s) {} }); 

Si el usuario ingresa un número con más de dos números después del punto decimal, se corregirá automáticamente.

¡Espero haber ayudado!

Esto funciona bien para mi. Permite ingresar el valor incluso después de cambiar el foco y recuperarlo. Por ejemplo: 123.00 , 12.12 , 0.01 , etc.

1. Integer.parseInt(getString(R.string.valuelength)) Especifica la longitud de los digits.Values entrada. digits.Values accede desde el string.xml string.xml. Es muy fácil cambiar los valores. 2. Integer.parseInt(getString(R.string.valuedecimal)) , esto es para el límite máximo de posiciones decimales.

 private InputFilter[] valDecimalPlaces; private ArrayList edittextArray; valDecimalPlaces = new InputFilter[] { new DecimalDigitsInputFilterNew( Integer.parseInt(getString(R.string.valuelength)), Integer.parseInt(getString(R.string.valuedecimal))) }; 

Matriz de valores EditText que permite realizar una acción.

 for (EditText etDecimalPlace : edittextArray) { etDecimalPlace.setFilters(valDecimalPlaces); 

I just used array of values that contain multiple edittext Next DecimalDigitsInputFilterNew.class file.

 import android.text.InputFilter; import android.text.Spanned; public class DecimalDigitsInputFilterNew implements InputFilter { private final int decimalDigits; private final int before; public DecimalDigitsInputFilterNew(int before ,int decimalDigits) { this.decimalDigits = decimalDigits; this.before = before; } @Override public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { StringBuilder builder = new StringBuilder(dest); builder.replace(dstart, dend, source .subSequence(start, end).toString()); if (!builder.toString().matches("(([0-9]{1})([0-9]{0,"+(before-1)+"})?)?(\\.[0-9]{0,"+decimalDigits+"})?")) { if(source.length()==0) return dest.subSequence(dstart, dend); return ""; } return null; } } 

This is to build on pinhassi’s answer – the issue that I came across was that you couldn’t add values before the decimal once the decimal limit has been reached. To fix the issue, we need to construct the final string before doing the pattern match.

 import java.util.regex.Matcher; import java.util.regex.Pattern; import android.text.InputFilter; import android.text.Spanned; public class DecimalLimiter implements InputFilter { Pattern mPattern; public DecimalLimiter(int digitsBeforeZero,int digitsAfterZero) { mPattern=Pattern.compile("[0-9]{0," + (digitsBeforeZero) + "}+((\\.[0-9]{0," + (digitsAfterZero) + "})?)||(\\.)?"); } @Override public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { StringBuilder sb = new StringBuilder(dest); sb.insert(dstart, source, start, end); Matcher matcher = mPattern.matcher(sb.toString()); if(!matcher.matches()) return ""; return null; } } 
 et = (EditText) vw.findViewById(R.id.tx_edittext); et.setFilters(new InputFilter[] { new DigitsKeyListener(Boolean.FALSE, Boolean.TRUE) { int beforeDecimal = 5, afterDecimal = 2; @Override public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { String temp = et.getText() + source.toString(); if (temp.equals(".")) { return "0."; } else if (temp.toString().indexOf(".") == -1) { // no decimal point placed yet if (temp.length() > beforeDecimal) { return ""; } } else { temp = temp.substring(temp.indexOf(".") + 1); if (temp.length() > afterDecimal) { return ""; } } return super.filter(source, start, end, dest, dstart, dend); } } }); 

Here is the TextWatcher that allow only n number of digits after decimal point.

TextWatcher

 private static boolean flag; public static TextWatcher getTextWatcherAllowAfterDeci(final int allowAfterDecimal){ TextWatcher watcher = 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 count, int after) { // TODO Auto-generated method stub } @Override public void afterTextChanged(Editable s) { // TODO Auto-generated method stub String str = s.toString(); int index = str.indexOf ( "." ); if(index>=0){ if((index+1) 

Cómo utilizar

 yourEditText.addTextChangedListener(getTextWatcherAllowAfterDeci(1)); 

The simplest way to achieve that is:

 et.addTextChangedListener(new TextWatcher() { public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { String text = arg0.toString(); if (text.contains(".") && text.substring(text.indexOf(".") + 1).length() > 2) { et.setText(text.substring(0, text.length() - 1)); et.setSelection(et.getText().length()); } } public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { } public void afterTextChanged(Editable arg0) { } }); 
 @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { String numero = total.getText().toString(); int dec = numero.indexOf("."); int longitud = numero.length(); if (dec+3 == longitud && dec != -1) { //3 number decimal + 1 log.i("ento","si"); numero = numero.substring(0,dec+3); if (contador == 0) { contador = 1; total.setText(numero); total.setSelection(numero.length()); } else { contador = 0; } } }