1

要求是限制用户在数字/十进制编辑文本字段中输入的十进制值不超过 1 个。也就是说,我还需要将数字条目限制为 6 Max 位数。例如。999999.9

如果用户单独输入数字 - 那么我应该能够将用户限制为最多 6 位数字,但应该允许“。” 和十进制数(如果由用户输入)。

我不确定,如何做到这一点。任何帮助和参考都会有很大帮助。

4

3 回答 3

4

也许一些类似的实现?我很确定它可以优化很多!

EditText et;
.....
// force number input type on edittext
et.setRawInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
et.addTextChangedListener(new CustomTextWatcher(et));

在哪里:

class CustomTextWatcher implements TextWatcher {
    private NumberFormat nf = NumberFormat.getNumberInstance();
    private EditText et;
    private String tmp = "";
    private int moveCaretTo;
    private static final int INTEGER_CONSTRAINT = 6;
    private static final int FRACTION_CONSTRAINT = 1;
    private static final int MAX_LENGTH = INTEGER_CONSTRAINT + FRACTION_CONSTRAINT + 1;

    public CustomTextWatcher(EditText et) {
        this.et = et;
        nf.setMaximumIntegerDigits(INTEGER_CONSTRAINT);
        nf.setMaximumFractionDigits(FRACTION_CONSTRAINT);
        nf.setGroupingUsed(false);
    }

    public int countOccurrences(String str, char c) {
        int count = 0;
        for (int i = 0; i < str.length(); i++) {
            if (str.charAt(i) == c) {
                count++;
            }
        }
        return count;
    }

    @Override
    public void afterTextChanged(Editable s) {
        et.removeTextChangedListener(this); // remove to prevent stackoverflow
        String ss = s.toString();
        int len = ss.length();
        int dots = countOccurrences(ss, '.');
        boolean shouldParse = dots <= 1 && (dots == 0 ? len != (INTEGER_CONSTRAINT + 1) : len < (MAX_LENGTH + 1));
        if (shouldParse) {
            if (len > 1 && ss.lastIndexOf(".") != len - 1) {
                try {
                    Double d = Double.parseDouble(ss);
                    if (d != null) {
                        et.setText(nf.format(d));
                    }
                } catch (NumberFormatException e) {
                }
            }
        } else {
            et.setText(tmp);
        }
        et.addTextChangedListener(this); // reset listener

        //tried to fix caret positioning after key type:
        if (et.getText().toString().length() > 0) {
            if (dots == 0 && len >= INTEGER_CONSTRAINT && moveCaretTo > INTEGER_CONSTRAINT) {
                moveCaretTo = INTEGER_CONSTRAINT;
            } else if (dots > 0 && len >= (MAX_LENGTH) && moveCaretTo > (MAX_LENGTH)) {
                moveCaretTo = MAX_LENGTH;
            }
            try {
                et.setSelection(et.getText().toString().length());
                // et.setSelection(moveCaretTo); <- almost had it :))
            } catch (Exception e) {
            }
        }
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        moveCaretTo = et.getSelectionEnd();
        tmp = s.toString();
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        int length = et.getText().toString().length();
        if (length > 0) {
            moveCaretTo = start + count - before;
        }
    }
}

不是 100%,但您可以用作基础并在其之上构建;)

编辑:尝试在文本更改后完善插入符号位置的设置,但这比我估计的要困难,并在每个字符输入后恢复到最后设置插入符号。我为插入符号留下了我开始使用的代码,也许你可以改进它?

于 2013-08-12T19:46:29.397 回答
2

上面的回答有一个小错误

我使用下面的代码编辑了那个。

import java.math.RoundingMode;
import java.text.NumberFormat;

import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;

public class DecimalTextWatcher implements TextWatcher {
    private NumberFormat numberFormat = NumberFormat.getNumberInstance();
    private EditText editText;
    private String temp = "";
    private int moveCaretTo;
    private int integerConstraint;
    private int fractionConstraint;
    private int maxLength;

    /**
     * Add a text watcher to Edit text for decimal formats
     * 
     * @param editText
     *            EditText to add DecimalTextWatcher
     * @param before
     *            digits before decimal point
     * @param after
     *            digits after decimal point
     */
    public DecimalTextWatcher(EditText editText, int before, int after) {
        this.editText = editText;
        this.integerConstraint = before;
        this.fractionConstraint = after;
        this.maxLength = before + after + 1;
        numberFormat.setMaximumIntegerDigits(integerConstraint);
        numberFormat.setMaximumFractionDigits(fractionConstraint);
        numberFormat.setRoundingMode(RoundingMode.DOWN);
        numberFormat.setGroupingUsed(false);
    }

    private int countOccurrences(String str, char c) {
        int count = 0;
        for (int i = 0; i < str.length(); i++) {
            if (str.charAt(i) == c) {
                count++;
            }
        }
        return count;
    }

    @Override
    public void afterTextChanged(Editable s) {
        // remove to prevent StackOverFlowException
        editText.removeTextChangedListener(this);
        String ss = s.toString();
        int len = ss.length();
        int dots = countOccurrences(ss, '.');
        boolean shouldParse = dots <= 1 && (dots == 0 ? len != (integerConstraint + 1) : len < (maxLength + 1));
        boolean x = false;
        if (dots == 1) {
            int indexOf = ss.indexOf('.');
            try {
                if (ss.charAt(indexOf + 1) == '0') {
                    shouldParse = false;
                    x = true;
                    if (ss.substring(indexOf).length() > 2) {
                        shouldParse = true;
                        x = false;
                    }
                }
            } catch (Exception ex) {
            }
        }
        if (shouldParse) {
            if (len > 1 && ss.lastIndexOf(".") != len - 1) {
                try {
                    Double d = Double.parseDouble(ss);
                    if (d != null) {
                        editText.setText(numberFormat.format(d));
                    }
                } catch (NumberFormatException e) {
                }
            }
        } else {
            if (x) {
                editText.setText(ss);
            } else {
                editText.setText(temp);
            }
        }
        editText.addTextChangedListener(this); // reset listener

        // tried to fix caret positioning after key type:
        if (editText.getText().toString().length() > 0) {
            if (dots == 0 && len >= integerConstraint && moveCaretTo > integerConstraint) {
                moveCaretTo = integerConstraint;
            } else if (dots > 0 && len >= (maxLength) && moveCaretTo > (maxLength)) {
                moveCaretTo = maxLength;
            }
            try {
                editText.setSelection(editText.getText().toString().length());
                // et.setSelection(moveCaretTo); <- almost had it :))
            } catch (Exception e) {
            }
        }
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        moveCaretTo = editText.getSelectionEnd();
        temp = s.toString();
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        int length = editText.getText().toString().length();
        if (length > 0) {
            moveCaretTo = start + count - before;
        }
    }
}

如下使用它..

itemCostEditText.addTextChangedListener(new DecimalTextWatcher(itemCostEditText, 6, 2));
于 2014-03-04T03:40:54.323 回答
0

您可以使用 TextWatcher 的 afterTextChanged/onTextChanged 方法来获取文本更改的通知,并使用 DecimalFormat 来格式化输入文本

http://developer.android.com/reference/java/text/DecimalFormat.html

http://developer.android.com/reference/android/text/TextWatcher.html

于 2013-08-09T06:56:00.100 回答