Search code examples
javaandroidandroid-edittext

Limit Decimal Places in Android EditText


I'm trying to write an app that helps you manage your finances. I'm using an EditText Field where the user can specify an amount of money.

I set the inputType to numberDecimal which works fine, except that this allows people to enter numbers such as 123.122 which is not perfect for money.

Is there a way to limit the number of characters after the decimal point to two?


Solution

  • This implementation of InputFilter solves the problem.

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