Android – 如何只允许一定数量的小数位

你知道任何方法,以确保用户只能input最大小数位数字。 我不知道如何解决这个问题。 在MS SQL数据库中,我将从我的应用程序发送数据我有这种types的decimal(8,3)decimal(8,3)现在考虑最终要存储我想要在Android中validation的值的列的数据types,我考虑过这两种情况:

  1. 如果用户input一个没有小数的数字,则最大位数必须是8
  2. 如果用户input一个带小数的数字,则最大的数字位数必须是8(包括小数点右边的数字)

现在我确定了第一个案子,但是对第二个案子没有太多的了解。 保持固定的最大位数(例如,总是8)是否正确? 还是应该考虑在小数点的左边和右边最多允许8个数字?

无论哪种方式,这是我一直在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) { } }); 

尽pipe如此,上面的代码处理了最大小数位数。 它不限制EditText中允许的总位数。

你认为你可以帮助我改进我的代码,以便处理EditText中允许的最大小数位数和总位数(考虑小数点左侧和右侧的两个数字)

编辑

那么,现在我正在尝试JoãoSousa的build议,以下是我所尝试的:

1)我定义了一个实现了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)试图使用这样的类:

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

Solutions Collecting From Web of "Android – 如何只允许一定数量的小数位"

我会用正则expression式的力量去编辑文本本身的filter。 首先是正则expression式:

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

也许有多种方法来改善这个expression式,但是这个技巧。

现在只需在edittext中设置一个inputfilter,如下所示:

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

顺便说一句,我只是testing这个代码,它是做什么的:

  1. 用户最多可以input8位数字;
  2. 只要用户input'。',允许的最大小数位数是8。

我是否正确理解你所描述的问题?

– 编辑

好吧,我快到了。 据我所知,十进制(8,3)最多8位数字,包括小数点左边或右边的数字,范围从-99999.99999999.999 。 至less这就是我从这句话中了解到的。 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 。 即使它是从MySQL文档MSSQL文档似乎也是如此。

我已经为你解答了,在这种情况下我也遭受了很多痛苦:D:P

我已经实现了这个最大的4位数的左侧和2小数点的右边,例如:4444.99

如此小的变化需要执行我所做的:需要做以下的改变

1)复制CustomTextWatcher.java来跟踪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)设置这个类来检查你的editText后面。

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

希望你可以根据你的需要转换我的代码。

你所描述的问题恰恰就是Masked EditText的意图。 🙂