I have an app with single numberdecimal EditText
. I want to filter digits before point from 1 to 120. And I want to allow user to input one digit after point.
Example: User can input 1, 2.3, 23, 45.7, 89.6, 119.9, 120.0 etc.
User can't input 3.34, 45.76, 89.652, 120.00, 121.00 etc.
How I can do that filter? Please, write me filter that work with EditText
on my terms)
Asked
Active
Viewed 1,624 times
2

musica
- 1,373
- 3
- 15
- 34

Олег Медведев
- 31
- 6
2 Answers
2
mEditText.setFilters(new InputFilter[]{new DigitsInputFilter(maxDigitsBeforeDot, maxDigitsAfterDot, maxValue)});
If you don't want to limit digits before or after dot just put Integer.MAX_VALUE
, to disable max value limit use Double.POSITIVE_INFINITY
.
public class DigitsInputFilter implements InputFilter {
private final String DOT = ".";
private int mMaxIntegerDigitsLength;
private int mMaxDigitsAfterLength;
private double mMax;
public DigitsInputFilter(int maxDigitsBeforeDot, int maxDigitsAfterDot, double maxValue) {
mMaxIntegerDigitsLength = maxDigitsBeforeDot;
mMaxDigitsAfterLength = maxDigitsAfterDot;
mMax = maxValue;
}
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
String allText = getAllText(source, dest, dstart);
String onlyDigitsText = getOnlyDigitsPart(allText);
if (allText.isEmpty()) {
return null;
} else {
double enteredValue;
try {
enteredValue = Double.parseDouble(onlyDigitsText);
} catch (NumberFormatException e) {
return "";
}
return checkMaxValueRule(enteredValue, onlyDigitsText);
}
}
private CharSequence checkMaxValueRule(double enteredValue, String onlyDigitsText) {
if (enteredValue > mMax) {
return "";
} else {
return handleInputRules(onlyDigitsText);
}
}
private CharSequence handleInputRules(String onlyDigitsText) {
if (isDecimalDigit(onlyDigitsText)) {
return checkRuleForDecimalDigits(onlyDigitsText);
} else {
return checkRuleForIntegerDigits(onlyDigitsText.length());
}
}
private boolean isDecimalDigit(String onlyDigitsText) {
return onlyDigitsText.contains(DOT);
}
private CharSequence checkRuleForDecimalDigits(String onlyDigitsPart) {
String afterDotPart = onlyDigitsPart.substring(onlyDigitsPart.indexOf(DOT), onlyDigitsPart.length() - 1);
if (afterDotPart.length() > mMaxDigitsAfterLength) {
return "";
}
return null;
}
private CharSequence checkRuleForIntegerDigits(int allTextLength) {
if (allTextLength > mMaxIntegerDigitsLength) {
return "";
}
return null;
}
private String getOnlyDigitsPart(String text) {
return text.replaceAll("[^0-9?!\\.]", "");
}
private String getAllText(CharSequence source, Spanned dest, int dstart) {
String allText = "";
if (!dest.toString().isEmpty()) {
if (source.toString().isEmpty()) {
allText = deleteCharAtIndex(dest, dstart);
} else {
allText = new StringBuilder(dest).insert(dstart, source).toString();
}
}
return allText;
}
private String deleteCharAtIndex(Spanned dest, int dstart) {
StringBuilder builder = new StringBuilder(dest);
builder.deleteCharAt(dstart);
return builder.toString();
}
}

Taras Smakula
- 331
- 2
- 7
0
You can implement your logic in onTextChanged
method of TextWatcher
editText.addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {}
@Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start,
}
});
Update For beginning You can use something like this:
editText.addTextChangedListener(new TextWatcher() {
boolean ignoreChange = false;
@Override
public void afterTextChanged(Editable s) {}
@Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
@Override
public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
if (!ignoreChange) {
String string = charSequence.toString();
String[] parts = string.split("\\.");
if (parts.length > 1) {
String digitsAfterPoint = parts[1];
if (digitsAfterPoint.length() > 1) {
ignoreChange = true;
editText.setText(string.substring(0, string.indexOf(".") + 2));
editText.setSelection(editText.getText().length());
ignoreChange = false;
}
}
}
}
});
But You also should control duplicates of "." symbol or something else.
Update #2 For value You can use, for example, that code:
editText.addTextChangedListener(new TextWatcher() {
boolean ignoreChange = false;
String beforeChange;
@Override
public void afterTextChanged(Editable s) {}
@Override
public void beforeTextChanged(CharSequence charSequence, int start,
int count, int after) {
}
@Override
public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
if (!ignoreChange) {
String string = charSequence.toString();
String[] parts = string.split("\\.");
if (parts.length > 1) {
String digitsAfterPoint = parts[1];
if (digitsAfterPoint.length() > 1) {
ignoreChange = true;
editText.setText(string.substring(0, string.indexOf(".") + 2));
editText.setSelection(editText.getText().length());
ignoreChange = false;
}
}
String strValue = editText.getText().toString();
float value = Float.valueOf(strValue);
if (value < 1 || value > 120) {
ignoreChange = true;
editText.setText(beforeChange);
editText.setSelection(editText.getText().length());
ignoreChange = false;
}
beforeChange = editText.getText().toString();
}
}
But You should carry about correct values input. And think about NumberPicker
or Spinner
for each digit.

Andrii Omelchenko
- 13,183
- 12
- 43
- 79
-
can you give me code for filter that I need. I am new in android programming – Олег Медведев Oct 22 '16 at 22:24
-
thank you, but how I can filter number before decimal point using your code? P.S. See my updated question: http://stackoverflow.com/questions/40210803/how-to-combine-input-fiters-for-numberdecimal-edittext – Олег Медведев Oct 24 '16 at 17:05