Android - How to allow only a certain number of decimal places

Do you know any method so that users can enter numbers with the maximum number of decimal places. I am not sure how to solve this problem. In an MS SQL database, I am going to send data from my application. I have columns with this decimal(8,3) type decimal(8,3) Now, looking at the data type of the column that will finally store the value I want to test on Android, I looked at these two cases:

  • If the user enters a number without decimals, the maximum number of digits must be 8
  • If the user enters a decimal number, the maximum number of digits must be 8 (including the digits to the right of the decimal point)

Now I'm sure in the first case, but not so much about the second. Is it correct to fix the number of maximum digits (for example, always 8)? Or should I consider entering a maximum of 8 digits to the left and 3 to the right of the decimal point?

Anyway, this is what I tried on 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) { } }); 

Although the code above handles the maximum number of decimal places. It does not limit the total number of digits allowed in EditText.

Do you think you could help me improve my code so that it processes both the maximum number of decimal places and the total number of digits allowed in EditText (given both numbers to the left and right of the decimal point)

EDIT

Ok, now I'm trying to suggest Joรฃo Sousa and this is what I tried:

1) I defined a class that implements 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) Tried to use the class as follows:

 mQuantityEditText.setFilters(new InputFilter[] { new NumberInputFilter(8,3)} ); 
+7
java android android-edittext
source share
3 answers

I would choose a filter in the editing text itself with the possibility of regular expression. First regex expression:

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

There may be several ways to improve this expression, but it does the trick.

And now just set the input filter in edittext, for example:

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

Btw, I just tested this code and what it does:

  • User can enter no more than 8 digits;
  • As soon as the user enters ".", The maximum allowable decimal digits are: 8.

Did I understand the problem you described?

- EDIT

OK, I was almost there. From what I understand, decimal (8.3) means no more than 8 digits, including the numbers to the left or right of the decimal point, from -99999.999 to 99999.999 . At least thatโ€™s what I understand from this 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 . Despite the fact that from the MySQL documentation, the MSSQL docs seem to do the same.

+8
source share

I have an answer for you, I also suffered a lot in a similar situation .: D: P

I implemented this for a maximum of 4 digits to the left and 2 to the right of the decimal point ex: 4444.99

therefore, for small changes, it is necessary to implement what I did: The following changes must be made.

1) copy CustomTextWatcher.java to track editText input.

 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) set this class to check your editText following.

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

Hope you can convert my code according to your needs.

+2
source share

The problem you are describing is exactly what Masked EditText is for . :)

0
source share

All Articles