限制Android EditText中的小数位数

我正在尝试编写一个可帮助您pipe理财务的应用程序。 我正在使用一个EditText字段,用户可以指定金额。

我将inputType设置为123.122 ,但是这样做可以让人们input123.122等不完美的数字。

有没有办法将小数点后面的字符数限制为两个?

更优雅的方式是使用正则expression式(正则expression式),如下所示:

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

要使用它:

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

简单的解决scheme,而不使用正则expression式:

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

使用:

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

InputFilter这个实现解决了这个问题。

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

以下是一个InputFilter示例,它只允许小数点前4位数字,之后最多1位数字。

edittext的值允许: 555.2,555.2

编辑文本块的值: 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的帮助下实现了这一点

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

此解决scheme不允许用户在小数点后input两位以上的数字。 您也可以在小数点前input任意数量的数字。 看到这个博客http://v4all123.blogspot.com/2013/05/set-limit-for-fraction-in-decimal.html设置多个EditText的filter。; 我希望这将有所帮助。 谢谢。

我为@Pinhassi解决scheme做了一些修复。 它处理一些情况:

你可以在任何地方移动光标

2.minus签名处理

3.digitsbefore = 2和digitsafter = 4,你input12.4545。 那么如果你想删除“。”,它将不允许。

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

我的解决scheme很简单,完美的作品!

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

用法:

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

我不喜欢另一种解决scheme,我创build了自己的解决scheme。 使用此解决scheme,您不能在点之前input超过MAX_BEFORE_POINT个数字,且小数点不能超过MAX_DECIMAL。

你只是不能input多余的数字,没有其他效果! 另外如果你写“。” 它键入“0”。

  1. 将布局中的EditText设置为:

    安卓的inputType = “numberDecimal”

  2. 添加监听器在你的onCreate。 如果要修改点前后的位数,请编辑PerfectDecimal(str,NUMBER_BEFORE_POINT,NUMBER_DECIMALS),将其设置为3和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. 包括这个function:

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

它完成了!

在将其放入TextView之前,请尝试使用NumberFormat.getCurrencyInstance()来格式化string。

就像是:

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

编辑 – 我没有在文档中find货币的inputType。 我想这是因为有一些货币不符合小数位的规则,比如日元。

正如LeffelMania所提到的,您可以通过使用上面的代码和EditText上设置的TextWatcher来更正用户input。

稍微改进@Pinhassi解决scheme。

工作得很好。 它validation连接的string。

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

要求是小数点后两位数。 小数点前的位数不应有任何限制 。 所以,解决办法应该是,

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

并将其用作,

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

感谢@Pinhassi的灵感。

这里的所有答案都非常复杂,我试图使它更简单。查看我的代码并自己决定 –

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

我已经修改了上面的解决scheme并创build了以下的一个 您可以设置小数点前后的位数。

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

}

我想出来的InputFilter允许你configuration小数点前后的位数。 另外,它不允许前导零。

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

这是什么,当你退出编辑阶段,它格式化字段为正确的格式。 在他们这一刻,它只有2个十进制字符。 我认为这是很简单的方法来做到这一点。

简单助手类在这里是为了防止用户input小数点后两位数以上:

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

这是我的解决scheme:

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

如果用户在小数点后input了两个以上的数字,则会自动更正。

我希望我能帮上忙

我也遇到过这个问题。 我希望能够在许多EditText中重用代码。 这是我的解决scheme:

用法:

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

类:

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

我真的很喜欢Pinhassi的回答,但是注意到用户在小数点后input了指定的数字位数后,不能再在小数点左边input文本。 问题在于解决scheme只testing了以前input的文本,而不是input的当前文本。 所以这里是我的解决scheme,将新的字符插入原始文本进行validation。

 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 

并调用设置editTextfilter

 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 

我改进了使用Pinhassi的正则expression式的解决scheme,所以它也正确处理边缘情况。 在检查input是否正确之前,首先根据android文档描述构build最终的string。

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

用法:

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

@你为..

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

一个非常迟的回应:我们可以这样做:

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

像其他人一样,我在我的项目中添加了这个类,并将筛选器设置为我想要的EditText

该filter是从@ Pixel的答案复制的。 我只是把它放在一起。

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

Now set the filter in your EditText like this.

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

Here one important thing is it does solves my problem of not allowing showing more than two digits after the decimal point in that EditText but the problem is when I getText() from that EditText , it returns the whole input I typed.

For example, after applying the filter over the EditText , I tried to set input 1.5699856987. So in the screen it shows 1.56 which is perfect.

Then I wanted to use this input for some other calculations so I wanted to get the text from that input field ( EditText ). When I called mEditText.getText().toString() it returns 1.5699856987 which was not acceptable in my case.

So I had to parse the value again after getting it from the EditText .

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

setScale does the trick here after getting the full text from the EditText .

This works fine for me. It allows value to be entered even after focus changed and retrieved back. For example: 123.00 , 12.12 , 0.01 , etc..

1. Integer.parseInt(getString(R.string.valuelength)) Specifies the length of the input digits.Values accessed from string.xml file.It is quiet easy to change values. 2. Integer.parseInt(getString(R.string.valuedecimal)) , this is for decimal places max limit.

 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 of EditText values that allows to perform action.

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

How to use

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