Android – Cómo permitir sólo un cierto número de lugares decimales

¿Conoce algún método para asegurarse de que los usuarios sólo pueden introducir cifras con un número máximo de decimales. No estoy seguro de cómo abordar este problema. En la base de datos MS SQL voy a enviar datos de mi aplicación Tengo columnas con este tipo decimal(8,3) Ahora, teniendo en cuenta el tipo de datos de la columna que finalmente va a almacenar el valor que quiero validar en Android , He considerado estos dos casos:

  1. Si el usuario introduce un número sin decimales, el número máximo de dígitos debe ser 8
  2. Si el usuario introduce un número con decimales, el número máximo de dígitos debe ser 8 (incluidos los dígitos a la derecha del punto decimal)

Ahora estoy seguro sobre el primer caso, pero no tanto sobre el segundo. ¿Es correcto mantener fijo el número de dígitos máximos (por ejemplo, siempre 8)? ¿O debo considerar permitir un máximo de 8 dígitos a la izquierda y 3 a la derecha de la coma decimal?

De cualquier manera esto es lo que he estado intentando en Android:

 mQuantityEditText.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable s) { String str = mQuantityEditText.getText().toString(); DecimalFormat format = (DecimalFormat) DecimalFormat .getInstance(); DecimalFormatSymbols symbols = format.getDecimalFormatSymbols(); char sep = symbols.getDecimalSeparator(); int indexOFdec = str.indexOf(sep); if (indexOFdec >= 0) { if (str.substring(indexOFdec, str.length() - 1).length() > 3) { s.replace(0, s.length(), str.substring(0, str.length() - 1)); } } } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } }); 

Aunque, el código anterior maneja el número máximo de decimales. No limita el número total de dígitos permitidos en el EditText.

¿Crees que podrías ayudarme a mejorar mi código para que maneje tanto el número máximo de decimales como el número total de dígitos permitidos en un EditText (considerando tanto los números a la izquierda como a la derecha del punto decimal)

EDITAR

Bueno, ahora estoy intentando lo que sugirió João Sousa y aquí está lo que he probado:

1) Definí una clase que implementa InputFilter

 public class NumberInputFilter implements InputFilter { private Pattern mPattern; public NumberInputFilter(int precision, int scale) { String pattern="^\\-?(\\d{0," + (precision-scale) + "}|\\d{0," + (precision-scale) + "}\\.\\d{0," + scale + "})$"; this.mPattern=Pattern.compile(pattern); } @Override public CharSequence filter(CharSequence source, int start, int end, Spanned destination, int destinationStart, int destinationEnd) { if (end > start) { // adding: filter // build the resulting text String destinationString = destination.toString(); String resultingTxt = destinationString.substring(0, destinationStart) + source.subSequence(start, end) + destinationString.substring(destinationEnd); // return null to accept the input or empty to reject it return resultingTxt.matches(this.mPattern.toString()) ? null : ""; } // removing: always accept return null; } } 

2) Trató de usar la clase así:

 mQuantityEditText.setFilters(new InputFilter[] { new NumberInputFilter(8,3)} ); 

Yo iría por un filtro en el propio texto de edición con el poder de regex. Primero la expresión regex:

 ^\-?(\d{0,5}|\d{0,5}\.\d{0,3})$ 

Tal vez hay varias maneras de mejorar esta expresión, pero esto no truco.

Y ahora acaba de establecer un filtro de entrada en el edittext, así:

 final String regex = "^\-?(\d{0,5}|\d{0,5}\.\d{0,3})$"; ((EditText)rootView.findViewById(R.id.editText1)).setFilters(new InputFilter[] { new InputFilter() { @Override public CharSequence filter(CharSequence source, int start, int end, Spanned destination, int destinationStart, int destinationEnd) { if (end > start) { // adding: filter // build the resulting text String destinationString = destination.toString(); String resultingTxt = destinationString.substring(0, destinationStart) + source.subSequence(start, end) + destinationString.substring(destinationEnd); // return null to accept the input or empty to reject it return resultingTxt.matches(regex) ? null : ""; } // removing: always accept return null; } } }); 

Por cierto, acabo de probar este código y lo que hace es:

  1. El usuario puede ingresar un máximo de 8 dígitos;
  2. Tan pronto como el usuario ingresa un '.', Los dígitos decimales máximos permitidos son 8.

¿Entendí correctamente el problema que describió?

– EDITAR

Ok, yo estaba casi allí. Por lo que entiendo, decimal (8,3) significa un máximo de 8 dígitos, incluyendo dígitos a la izquierda o derecha del punto decimal, que van desde -99999.999 a 99999.999 . Por lo menos eso es lo que entiendo de esta frase Standard SQL requires that DECIMAL(5,2) be able to store any value with five digits and two decimals, so values that can be stored in the salary column range from -999.99 to 999.99 . A pesar de que es de la documentación de MySQL los documentos MSSQL parecen hacer lo mismo.

Tengo respuesta para usted, yo también sufrido mucho en este tipo de situation.:D: P

He implementado esto para un máximo de 4 dígitos a la izquierda y 2 a la derecha del punto decimal ex: 4444.99

Tan pequeños cambios necesitan para implementar lo que hice: Necesidad de hacer los siguientes cambios

1) copia CustomTextWatcher.java para rastrear la entrada de editText.

 import java.text.NumberFormat; import android.text.Editable; import android.text.TextWatcher; import android.util.Log; import android.widget.EditText; public class CustomTextWatcher implements TextWatcher { private NumberFormat nf = NumberFormat.getNumberInstance(); private EditText et; private String tmp = ""; private int moveCaretTo; private static final int INTEGER_CONSTRAINT = 4; private static final int FRACTION_CONSTRAINT = 2; private static final int MAX_LENGTH = INTEGER_CONSTRAINT + FRACTION_CONSTRAINT + 1; public CustomTextWatcher(EditText et) { this.et = et; nf.setMaximumIntegerDigits(INTEGER_CONSTRAINT); nf.setMaximumFractionDigits(FRACTION_CONSTRAINT); nf.setGroupingUsed(false); } public int countOccurrences(String str, char c) { int count = 0; for (int i = 0; i < str.length(); i++) { if (str.charAt(i) == c) { count++; } } return count; } @Override public void afterTextChanged(Editable s) { et.removeTextChangedListener(this); // remove to prevent stackoverflow String ss = s.toString(); int len = ss.length(); int dots = countOccurrences(ss, '.'); boolean shouldParse = dots <= 1 && (dots == 0 ? len != (INTEGER_CONSTRAINT + 1) : len < (MAX_LENGTH + 1)); if (shouldParse) { if (len > 1 && ss.lastIndexOf(".") != len - 1) { try { if (ss.contains(".")) { String[] integerFractionStrings = ss.split("\\."); Log.v("Check SS ", ss); Log.v("second string", "Found" + integerFractionStrings.length); if (integerFractionStrings.length > 1) { Log.v("integerFractionStrings", integerFractionStrings[1]); if (integerFractionStrings[1].length() == 1 && integerFractionStrings[1].charAt(0) == '0') { et.setText(ss); Log.v("second string", "size 1"); } else { Log.v("second string", "> 1"); Double d = Double.parseDouble(ss); if (d != null) { et.setText(nf.format(d)); } } } } else { Log.v("First string", "No dot"); Double d = Double.parseDouble(ss); if (d != null) { et.setText(nf.format(d)); } } } catch (NumberFormatException e) { } } } else { Log.v("second string", "size 1"); et.setText(tmp); } et.addTextChangedListener(this); // reset listener // tried to fix caret positioning after key type: if (et.getText().toString().length() > 0) { if (dots == 0 && len >= INTEGER_CONSTRAINT && moveCaretTo > INTEGER_CONSTRAINT) { moveCaretTo = INTEGER_CONSTRAINT; } else if (dots > 0 && len >= (MAX_LENGTH) && moveCaretTo > (MAX_LENGTH)) { moveCaretTo = MAX_LENGTH; } try { et.setSelection(et.getText().toString().length()); // et.setSelection(moveCaretTo); <- almost had it :)) } catch (Exception e) { } } } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { moveCaretTo = et.getSelectionEnd(); tmp = s.toString(); } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { int length = et.getText().toString().length(); if (length > 0) { moveCaretTo = start + count - before; } } } 

2) Establezca esta clase para comprobar su editText siguiendo.

 EditText review_food_Price; review_food_Price = (EditText) findViewById(R.id.food_Price); review_food_Price.setRawInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL); review_food_Price.addTextChangedListener(new CustomTextWatcher( review_food_Price)); 

Esperanza usted puede convertir mi código según su necesidad.

El problema que describen es precisamente lo que se pretende utilizar para un Texto de edición enmascarado . 🙂

  • Cómo el calendario de Google o Instagram hacer sus aplicaciones todo el tiempo en marcha y funcionando incluso después de la parada de fuerza
  • Implementación de Instagram como sistema de navegación en aplicaciones en Android
  • ¿Todos los dispositivos android tienen la carpeta "sdcard"?
  • Actualizar elementos en un objeto JSONO
  • Android / Java Append String + int
  • Conexión de socket SSL
  • ¿Es posible que un método de devolución de llamada se llame después de onDestroy?
  • Arrastrar y soltar + dibujo personalizado en Android
  • Error al entregar el resultado ResultInfo
  • 'While' no puede completar sin lanzar una excepción - Android
  • Problema de análisis de Json (valores cambiados automáticamente flotante)
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.