Ограничить десятичные места в Android EditText

Я пытаюсь написать приложение, которое поможет вам управлять своими финансами. Я использую поле EditText где пользователь может указать сумму денег.

Я устанавливаю inputType на numberDecimal который работает нормально, за исключением того, что это позволяет людям вводить числа, такие как 123.122 что не идеально подходит для денег.

Есть ли способ ограничить число символов после десятичной точки двумя?

Solutions Collecting From Web of "Ограничить десятичные места в Android EditText"

Более элегантный способ будет использовать регулярное выражение (regex) следующим образом:

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

Упрощенное решение без использования регулярных выражений:

 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

Значения, которые являются блоками edittext: 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++; } } } }); 

Это решение не позволит пользователю вводить более двух цифр после десятичной точки. Также вы можете ввести любое количество цифр до десятичной точки. См. Этот блог http://v4all123.blogspot.com/2013/05/set-limit-for-fraction-in-decimal.html, чтобы установить фильтр для нескольких EditText. Я надеюсь, это поможет. Спасибо.

Я сделал некоторые исправления для решения @Pinhassi. Он обрабатывает некоторые случаи:

1.Вы можете перемещать курсор в любом месте

2.minus sign handling

3.digitsbefore = 2 и digitsafter = 4, и вы вводите 12.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 ""; } } 

Мое решение прост и прекрасно работает!

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

Мне не нравится другое решение, и я создал свой собственный. С помощью этого решения вы не можете ввести больше, чем MAX_BEFORE_POINT, цифру до точки, а десятичные числа не могут превышать MAX_DECIMAL.

Вы просто не можете вводить цифру в избытке, никаких других эффектов! В дополнение, если вы пишете «.». Он вводит "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. Включите этот Funcion:

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

И все!

Попробуйте использовать NumberFormat.getCurrencyInstance (), чтобы отформатировать строку перед тем, как поместить ее в TextView.

Что-то вроде:

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

Изменить. Нет значения типа ввода для валюты, которую я мог бы найти в документах. Я предполагаю, что это связано с тем, что существуют некоторые валюты, которые не соответствуют тому же правилу для десятичных знаков, таких как японская иена.

Как упоминал LeffelMania, вы можете исправить пользовательский ввод, используя вышеуказанный код с TextWatcher который установлен в вашем EditText .

Немного улучшенное решение @Pinhassi.

Работает очень хорошо. Он проверяет конкатенированные строки.

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

Требование – 2 цифры после десятичной. Не должно быть предела для цифр до десятичной точки. Итак, решение должно быть,

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

InputFilter, с которым я столкнулся, позволяет вам настроить количество цифр до и после десятичного разряда. Кроме того, он запрещает начало нулей.

 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 десятичных символа. Я думаю, что это довольно простой способ сделать это.

Я изменил приведенные выше решения и создал следующий. Вы можете установить количество цифр до и после десятичной точки.

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

}

Класс Simple Helper предназначен для предотвращения ввода пользователем более двух цифр после десятичной дроби:

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

Вот мое решение:

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

Если пользователь вводит число с более чем двумя числами после десятичной точки, оно будет автоматически исправлено.

Надеюсь, я помог!

Я также столкнулся с этой проблемой. Я хотел иметь возможность повторно использовать код во многих EditTexts. Это мое решение:

Применение :

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

Мне очень понравился ответ Пинхасси, но заметил, что после того, как пользователь ввел указанные цифры числа после десятичной точки, вы больше не могли вводить текст в левую часть десятичной точки. Проблема заключалась в том, что решение тестировало только предыдущий текст, который был введен, а не текущий текст. Итак, вот мое решение, которое вставляет новый символ в исходный текст для проверки.

 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 

И вызов для установки фильтра 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 

Я улучшил решение, использующее регулярное выражение Pinhassi, так что он также правильно обрабатывает края. Прежде чем проверять правильность ввода, сначала создается окончательная строка, как описано в документах 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; } } 

Применение:

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

@Meh для u ..

 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 я хочу.

Фильтр копируется из ответа @ 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 ""; } } 

Теперь установите фильтр в свой EditText следующим образом.

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

Здесь одна важная вещь заключается в том, что она решает мою проблему, не позволяя показывать более двух цифр после десятичной точки в этом EditText но проблема в том, когда я getText() из этого EditText , он возвращает весь введенный мной ввод.

Например, после применения фильтра над EditText я попытался установить ввод 1.5699856987. Так что на экране это показывает 1.56, что идеально.

Затем я хотел использовать этот ввод для некоторых других вычислений, поэтому я хотел получить текст из этого поля ввода ( EditText ). Когда я вызывал mEditText.getText().toString() возвращает 1.5699856987, что было неприемлемо в моем случае.

Поэтому мне пришлось анализировать значение снова после получения его из EditText .

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

setScale делает трюк здесь после получения полного текста из EditText .

Это отлично работает для меня. Он позволяет вводить значение даже после изменения фокуса и возврата назад. Например: 123.00 , 12.12 , 0.01 и т. Д.

1. Integer.parseInt(getString(R.string.valuelength)) Определяет длину входных digits.Values доступны из string.xml string.xml. Типично легко изменить значения. 2. Integer.parseInt(getString(R.string.valuedecimal)) , это максимальный предел десятичных знаков.

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

Массив значений EditText который позволяет выполнять действия.

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

Я просто использовал массив значений, которые содержат несколько файлов edittext Next DecimalDigitsInputFilterNew.class .

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

Это должно основываться на ответе pinhassi – проблема, с которой я столкнулся, заключалась в том, что вы не могли добавлять значения до десятичного знака после достижения десятичного предела. Чтобы исправить проблему, нам нужно построить финальную строку перед выполнением соответствия шаблону.

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

Как использовать

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