Android - Comma as decimal separator on Numeric Keyboard

Kaushal Panjwani picture Kaushal Panjwani · Jun 13, 2012 · Viewed 7k times · Source

We need to have a numeric keyboard for an EditText. The Keyboard should have decimal separator based on the device's selected locale. We implemented this by setting the custom DigitsKeyListener to the EditText

public class NumericDigitsKeyListener extends DigitsKeyListener {


    @Override
    protected char[] getAcceptedChars() {

        char[] acceptedCharacters = null;

            acceptedCharacters =  new char[] {
                    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                    new DecimalFormatSymbols(Locale.getDefaultLocale()).getDecimalSeparator()

        return acceptedCharacters;
    }

    /**
     * @see android.text.method.DigitsKeyListener#getInputType()
     */
    public int getInputType() {
        return InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL;
    }

The above seems to work fine for most of the devices however for Samsung Galaxy S-II, the softkeyboard does not have comma in the keyboard.Th swype keyboard of the device displays the comma, but the default one does not.

I have tried overriding DigitsKeyListener as mentioned here

Is there a way I can enforce all the devices to have comma (when applicable or even always) to be there on numeric keyboard?

Answer

Pedro Andrade picture Pedro Andrade · Feb 20, 2013

I think that your code has the same problem as using:

android:inputType="numberDecimal" android:digits="0123456789,"

(except that your code is more generic)

The problem - as I understand, is that some keyboards just don't respect digits property when inputType is numberDecimal. This is a documented bug and the only way I found to avoid this behaviour is to use inputType="text" and set a input filter to restrict characters. Of course, the keyboard isn't proper for numbers but couldn't find a better solution. The filter would be something like this:

mEditText.setFilters(new InputFilter[] { new DecimalInputFilter() });


public class DecimalInputFilter implements InputFilter {

    private static final String ALLOWED_CHARS = "0123456789,";

    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        if (source instanceof SpannableStringBuilder) {
            final SpannableStringBuilder sourceAsSpannableBuilder = (SpannableStringBuilder)source;
            for (int i = end - 1; i >= start; i--) { 
                final char currentChar = source.charAt(i);
                 if (!StringUtils.contains(ALLOWED_CHARS, currentChar)) {    
                     sourceAsSpannableBuilder.delete(i, i+1);
                 }     
            }
            return source;
        } else {
            final StringBuilder filteredStringBuilder = new StringBuilder();
            for (int i = 0; i < end; i++) { 
                final char currentChar = source.charAt(i);
                if (StringUtils.contains(ALLOWED_CHARS, currentChar)) {    
                    filteredStringBuilder.append(currentChar);
                }     
            }
            return filteredStringBuilder.toString();
        }
    }
}