可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have an EditText
box which have to allow user to enter upto 7 numbers and two decimal places. After entering seven digits,it should not allow to add one more digit but i may allow upto 2 decimal places. I use a decimal filter for 2 decimal places and this code in XML
android:maxLength="7"
android:imeOptions="actionDone"
android:inputType="numberDecimal"
But EditText
is allowing to enter
8 digits. How can this be solved?
回答1:
Try this under onCreate
youreditText.setFilters(new InputFilter[] {new DecimalDigitsInputFilter(5,1)});
this anywhere in your program
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;
}
}
回答2:
You can user this input filter to solve your problem.
To set filter:
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
.
You can use this filter for text fields where you enter numbers or numbers and text.
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();
}
}
I hope it helps you.
回答3:
edittext.setFilters(new InputFilter[] { new DigitsKeyListener(
Boolean.FALSE, Boolean.TRUE) {
int beforeDecimal = 7, afterDecimal = 2;
@Override
public CharSequence filter(CharSequence source, int start, int end,
Spanned dest, int dstart, int dend) {
String etText = edittext.getText().toString();
if (etText.isEmpty()){
return null;
}
String temp = edittext.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 = edittext.getSelectionStart();
if (etText.indexOf(".") == -1) {
Log.i("First time Dot", etText.toString().indexOf(".")+" "+etText);
dotPosition = temp.indexOf(".");
Log.i("dot Positon", cursorPositon+"");
Log.i("dot Positon", etText+"");
Log.i("dot Positon", dotPosition+"");
}else{
dotPosition = etText.indexOf(".");
Log.i("dot Positon", cursorPositon+"");
Log.i("dot Positon", etText+"");
Log.i("dot Positon", dotPosition+"");
}
if(cursorPositon <= dotPosition){
Log.i("cursor position", "in left");
String beforeDot = etText.substring(0, dotPosition);
if(beforeDot.length()<beforeDecimal){
return source;
}else{
if(source.toString().equalsIgnoreCase(".")){
return source;
}else{
return "";
}
}
}else{
Log.i("cursor position", "in right");
temp = temp.substring(temp.indexOf(".") + 1);
if (temp.length() > afterDecimal) {
return "";
}
}
}
return super.filter(source, start, end, dest, dstart, dend);
}
} });
回答4:
public class DecimalDigitsInputFilter implements InputFilter {
Pattern mPattern;
int digitsBeforeZero;
public DecimalDigitsInputFilter(int digitsBeforeZero, int digitsAfterZero) {
this.digitsBeforeZero = digitsBeforeZero;
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()) {
if (dest.toString().contains(".")) {
if (dest.toString().substring(dest.toString().indexOf(".")).length() > 2) {
return "";
}
return null;
} else if (!Pattern.compile("[0-9]{0," + (digitsBeforeZero - 1) + "}").matcher(dest).matches()) {
if (!dest.toString().contains(".")) {
if (source.toString().equalsIgnoreCase(".")) {
return null;
}
}
return "";
} else {
return null;
}
}
return null;
}
}
回答5:
You can user this input filter to solve your problem. To set filter:
For 4 digits and Two Decimal points
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) {
String s = Html.toHtml(dest).replaceAll("\\<.*?>","").replaceAll("\n","");
Matcher matcher = mPattern.matcher(dest);
if (!matcher.matches())
return "";
try {
if(Double.parseDouble(s)<9999.99 && s.contains(".")) {
return null;
}else if ((Double.parseDouble(s)<1000 && !s.contains("."))||source.equals(".")) {
return null;
}else {
return "";
}
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
editText.setFilters(new InputFilter[]{new DecimalDigitsInputFilter(7, 2)});
回答6:
Though not a direct solution, you can control every character that goes form IME to EditText via TextWatcher
One of SO Q&A on how to use TextWatcher
is here
More about TextWatcher
is here
You might need help of Regular expression to match floating point precision & pattern matcher to validate input.
回答7:
You can enhance it when using Android databinding like this:
Define custom binding adapter:
@BindingAdapter({"digitsBeforeZero", "digitsAfterZero"})
public void bindAmountInputFilter(EditText view, int digitsBeforeZero, int digitsAfterZero) {
view.setFilters(new InputFilter[]{new DecimalDigitsInputFilter(digitsBeforeZero, digitsAfterZero)});
}
Add attributes to EditText:
app:digitsBeforeZero="@{7}"
app:digitsAfterZero="@{2}"
and it will automatically set the input filter for the edittext
回答8:
editText.addTextChangedListener(new TextWatcher() {
String firstString;
String beforeInt = "";
String beforeDec = "";
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
txtAmt.setText("");
firstString = charSequence.toString();
String[] rupee = firstString.split("\\.");
if ( rupee.length > 0 )
beforeInt = rupee[0];
if ( rupee.length > 1 )
beforeDec = rupee[1];
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
try {
String amount = charSequence.toString().replaceAll(",","");
if ( txtAmt != null && !amount.isEmpty()){
String[] rupee = amount.split("\\.");
if ( rupee.length == 0 )
return;
String intPart = rupee[0];
int arrayLength = rupee.length;
if ( arrayLength == 2 ){
String decPart = rupee[1];
if ( decPart.length() == 1 )
decPart += "0";
if ( intPart.length() > 6 || decPart.length() > 2 ){
editText.removeTextChangedListener(this);
firstString = beforeInt;
if ( !beforeDec.isEmpty() )
firstString += "."+beforeDec;
editText.setText( firstString );
editText.setSelection( firstString.length());
editText.addTextChangedListener( this );
}
}
}
}catch (Exception e){
//Do nothing
}
}
@Override
public void afterTextChanged(Editable s) {
//Do nothing
}
});