【问题标题】:How to limit EditText length to 7 integers and 2 decimal places?如何将 EditText 长度限制为 7 个整数和 2 个小数位?
【发布时间】:2025-05-25 08:45:01
【问题描述】:

我有一个EditText 框,它必须允许用户输入最多 7 个数字和两个小数位。输入七位数字后,不应再添加一位数字,但我可以允许最多两位小数。我对 2 个小数位使用十进制过滤器,并在 XML 中使用此代码

android:maxLength="7"    
android:imeOptions="actionDone"                  
android:inputType="numberDecimal"

EditText 允许enter 8 位数字。怎么解决?

【问题讨论】:

  • 尝试使用“#####.##”格式...

标签: android android-layout android-edittext


【解决方案1】:

在 onCreate 下试试这个

 youreditText.setFilters(new InputFilter[] {new DecimalDigitsInputFilter(5,1)});

程序中的任何位置

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

        }

【讨论】:

  • 此解决方案有效,但是当您尝试再次编辑输入的值时,它将不允许您重新输入小数点之前的任何内容,直到您清除所有内容,因此@Taras Smakula 答案更正确跨度>
【解决方案2】:

您可以使用此输入过滤器来解决您的问题。 设置过滤器:

mEditText.setFilters(new InputFilter[]{new DigitsInputFilter(maxDigitsBeforeDot, maxDigitsAfterDot, maxValue)});

如果您不想限制点之前或之后的数字,只需输入Integer.MAX_VALUE禁用最大值限制使用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();
    }
}

希望对你有帮助。

【讨论】:

  • 我使用了您的代码,并将最大长度设置为 Double.POSITIVE_INFINITY。因为我只需要小数点前 7 位数字和小数点后 2 位数字。如果我第一次进入,它会起作用。当我在编辑文本中编辑值时,它会采用尽可能多的值。你能帮我解决一下吗?
  • 谢谢这是我需要的
【解决方案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);
            }
        } });

【讨论】:

  • DigitsKeyListener 已弃用
【解决方案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;
    }
}

【讨论】:

  • 如果存在逗号千位分隔符,这将无法正常工作。假设如果编辑文本是使用英语语言环境使用数字格式格式化的,则每个数字 > 999 都会有一个逗号,并且这些数字将不匹配使用 ur 模式,因此当将数字 4,500.00 更改为 5600 时,只会显示 600。
【解决方案5】:

您可以使用此输入过滤器来解决您的问题。设置过滤器: 对于 4 位数字和两个小数点

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

【讨论】:

  • 如果用户先输入小数位,此解决方案会出错.. 比如说 0.25 并且用户先输入小数点
【解决方案6】:

首先在 onCreate 中创建这个

DecimalFormat amountFormate  = new DecimalFormat("#######.##");
amountFormate.setMinimumFractionDigits(2);
amountFormate.setMaximumFractionDigits(2);
editText.setText(amountFormate.format(yourValue));
  1. 2 是您的小数位数
  2. yourValue 只不过是双变量

示例:

double amount = 1234567.54;
editText.setText(amountFormate.format(amount));

输出-> 1234567.54

【讨论】:

    【解决方案7】:

    虽然不是直接的解决方案,但您可以通过 TextWatcher 控制从 IME 到 EditText 的每个字符

    关于如何使用TextWatcher 的SO Q&A 之一是here

    更多关于TextWatcher的是here

    您可能需要Regular expression to match floating point precisionpattern matcher 的帮助来验证输入。

    【讨论】:

      【解决方案8】:

      您可以像这样使用 Android 数据绑定来增强它:

      定义自定义绑定适配器:

      @BindingAdapter({"digitsBeforeZero", "digitsAfterZero"})
      public void bindAmountInputFilter(EditText view, int digitsBeforeZero, int digitsAfterZero) {
             view.setFilters(new InputFilter[]{new DecimalDigitsInputFilter(digitsBeforeZero, digitsAfterZero)});
       }
      

      为 EditText 添加属性:

      app:digitsBeforeZero="@{7}"
      app:digitsAfterZero="@{2}"
      

      它会自动为编辑文本设置输入过滤器

      【讨论】:

        【解决方案9】:
        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
                }
            });
        

        【讨论】: