Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Limitar los lugares decimales en Android EditText

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

Puse el inputType a numberDecimal que funciona bien, excepto que esto permite a la gente para introducir números como 123.122 que no es perfecto para el dinero.

  • Barra de acción de corte / copia personalizada para EditText que muestra las manijas de selección de texto
  • ¿Cómo puedo determinar que CollapsingToolbar está contraído?
  • OnViewCreated - lugar equivocado para reemplazar el fragmento?
  • SearchView on support.v7.appcompat problema de la biblioteca: el fondo de 9 parches predeterminado no se procesa correctamente
  • Emulador de tableta android
  • Determinar si dos objetos Java son de la misma clase
  • ¿Hay una manera de limitar el número de caracteres después del punto decimal a dos?

  • Android ListView con encabezado y pie de página fijos
  • Emulador: ADVERTENCIA: No se pudo inicializar la emulación de OpenGLES, utilizando software renderer
  • Se suscribió renovación en la aplicación en android
  • Cómo generar una suma de verificación MD5 para un archivo en Android?
  • ¿Cómo puedo escalar las vistas de texto usando transiciones de elementos compartidos?
  • Menús dinámicos en NavigationView
  • 30 Solutions collect form web for “Limitar los lugares decimales en Android EditText”

    Una forma 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 hacer:

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

    Solución más sencilla sin utilizar 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 sólo 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 edittext bloquea: 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 introducir cualquier número de dígitos antes del punto decimal. Vea este blog http://v4all123.blogspot.com/2013/05/set-limit-for-fraction-in-decimal.html para establecer el filtro para múltiples EditText. Espero que esto sea de ayuda. Gracias.

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

    1.you puede mover el cursor dondequiera

    2. Manejo de signos de minúsculos

    3.digitsbefore = 2 y digitsafter = 4 e ingresa 12.4545. Entonces, si desea eliminar ".", No lo 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; restorePreviousValue(); } } else { mRestoringPreviousValueFlag = false; } } private void restorePreviousValue() { 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 puede introducir más de MAX_BEFORE_POINT dígitos antes del punto y los decimales no pueden ser más de MAX_DECIMAL.

    Usted simplemente no puede 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 de edición de 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. Incluya esta Función:

       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 está hecho!

    Intente usar NumberFormat.getCurrencyInstance () para dar formato a 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 podría encontrar en los documentos. Me imagino que esto es porque hay algunas monedas que no siguen la misma regla para los decimales, como el yen japonés.

    Como LeffelMania mencionado, puede corregir la entrada de usuario utilizando el código anterior con un TextWatcher que se establece 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 2 dígitos después de decimal. No debe haber límite para los dígitos antes del punto decimal. Por lo tanto, la solución debe 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 utilizarlo como,

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

    Gracias a @Pinhassi por la inspiración.

    Todas las respuestas aquí son bastante complejas. Intenté hacerlo mucho más simple. 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()<temp) { if(!editText.getText().toString().contains(".")) editText.setFilters(new InputFilter[] { new InputFilter.LengthFilter(editText.getText().toString().length()-1) }); else editText.setFilters(new InputFilter[] { new InputFilter.LengthFilter(editText.getText().toString().length()+1) }); } if(!editText.getText().toString().contains(".")) { editText.setFilters(new InputFilter[] { new InputFilter.LengthFilter(editText.getText().toString().length()+1) }); check=0; } else if(check==0) { check=1; editText.setFilters(new InputFilter[] { new InputFilter.LengthFilter(editText.getText().toString().length()+2) }); } } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { temp = editText.getText().toString().length(); } @Override public void afterTextChanged(Editable s) { // TODO Auto-generated method stub } }); 

    El InputFilter que surgió le permite configurar el número de dígitos antes y después del punto 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)}); 
     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 esto es cuando sale de la fase de edición que formatea el campo al formato correcto. En estos momentos tiene sólo 2 caracteres decimales. Creo que esta es una manera bastante fácil de hacer esto.

    He modificado las soluciones anteriores y he creado la 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); } 

    }

    La clase Simple Helper está aquí para evitar que el usuario ingrese más de 2 dígitos después de 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); } } 

    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 introduce un número con más de dos números después del punto decimal, se corregirá automáticamente.

    Espero haber ayudado!

    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<len; i++){ if(nr.charAt(i)=='.'){ pos=i+1; break; } } return len-pos; } } 

    Realmente me gustó la respuesta de Pinhassi, pero noté que después de que el usuario hubiera introducido los dígitos de número especificado después del punto decimal ya no podría introducir texto en el lado izquierdo del punto decimal. El problema era que la solución sólo probaba el texto anterior que se había introducido, no el texto actual que se introdujo. Así que aquí está mi solución que inserta el nuevo carácter en el texto original para la 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 

    He mejorado en la solución que utiliza un regex por Pinhassi por lo que también maneja los casos de borde correctamente. Antes de comprobar 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)}); 

    Me alegro por 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()<beforeDecimal){ return source; }else{ if(source.toString().equalsIgnoreCase(".")){ return source; }else{ return ""; } } }else{ temp = temp.substring(temp.indexOf(".") + 1); if (temp.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 otros dijeron, agregué esta clase en mi proyecto y EditText el filtro al EditText que deseo.

    El filtro se copia desde la respuesta de @ Pixel. Sólo 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 establece el filtro en tu EditText como este.

     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 que EditText pero el problema es cuando getText() de ese EditText , que devuelve toda la entrada que EditText .

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

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

    Así que tuve que analizar el valor de nuevo después de obtenerlo desde el 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 la EditText .

    Esto funciona bien para mi. Permite introducir 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 string.xml file.It es tranquilo fácil de cambiar los valores. 2. Integer.parseInt(getString(R.string.valuedecimal)) , esto es para el límite máximo de decimales.

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

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

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

    Acabo de utilizar la matriz de valores que contienen varios edittext Next DecimalDigitsInputFilterNew.class archivo.

     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)<str.length()){ String numberD = str.substring(index+1); if (numberD.length()!=allowAfterDecimal) { flag=true; }else{ flag=false; } }else{ flag = false; } }else{ flag=false; } if(flag) s.delete(s.length() - 1, s.length()); } }; return watcher; } 

    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) { } }); 

    I have changed answer №6 (by Favas Kv) because there You can put just point in the first position.

     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; } }}; 
     @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; } } } 
    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.