Decimal separator comma (',') with numberD

2019-01-03 08:50发布

The inputType numberDecimal in EditText uses the dot '.' as decimal separator. In Europe it's common to use a comma ',' instead. Even though my locale is set as german the decimal separator is still the '.'

Is there a way to get the comma as decimal separator?

18条回答
闹够了就滚
2楼-- · 2019-01-03 09:45

A variation on the 'digit' solutions offered here:

char separator = DecimalFormatSymbols.getInstance().getDecimalSeparator();
input.setKeyListener(DigitsKeyListener.getInstance("0123456789" + separator));

Taking into account the locale separator.

查看更多
叛逆
3楼-- · 2019-01-03 09:48

Following Code Currency Mask for EditText ($ 123,125.155)

Xml Layout

  <EditText
    android:inputType="numberDecimal"
    android:layout_height="wrap_content"
    android:layout_width="200dp"
    android:digits="0123456789.,$" />

Code

EditText testFilter=...
testFilter.addTextChangedListener( new TextWatcher() {
        boolean isEdiging;
        @Override public void onTextChanged(CharSequence s, int start, int before, int count) { }
        @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { }

        @Override public void afterTextChanged(Editable s) {
            if(isEdiging) return;
            isEdiging = true;

            String str = s.toString().replaceAll( "[^\\d]", "" );
            double s1 = Double.parseDouble(str);

            NumberFormat nf2 = NumberFormat.getInstance(Locale.ENGLISH);
            ((DecimalFormat)nf2).applyPattern("$ ###,###.###");
            s.replace(0, s.length(), nf2.format(s1));

            isEdiging = false;
        }
    });
查看更多
Emotional °昔
4楼-- · 2019-01-03 09:48

My solution is:

  • In main activity:

    char separator =DecimalFormatSymbols.getInstance().getDecimalSeparator(); textViewPitchDeadZone.setKeyListener(DigitsKeyListener.getInstance("0123456789" + separator));

  • In xml file: android:imeOptions="flagNoFullscreen" android:inputType="numberDecimal"

and I took the double in the editText as a String.

查看更多
乱世女痞
5楼-- · 2019-01-03 09:48

I can confirm that the fixes proposed do not work on Samsung IMEs (at least on S6 and S9) and maybe LG. They still show a dot as decimal separator regardless of locale. Switching to Google's IME fixes this but is hardly an option for most developers.

It also has not been fixed in Oreo for these keyboards since it is a fix that Samsung and/or LG have to do and then to push even to their ancient handsets.

I have instead forked the number-keyboard project and added a mode where it behaves like an IME: fork. See the project sample for details. This has worked quite well for me and is similar to many of the "PIN entry" fake IMEs you see in banking apps.

Sample app screenshot

查看更多
神经病院院长
6楼-- · 2019-01-03 09:48

It's more than 8 years passed and I am surprised, this issue isn't fixed yet...
I struggled with this simple issue since the most upvoted answer by @Martin lets typing multiple separators, i.e. user can type in "12,,,,,,12,1,,21,2,"
Also, the second concern is that on some devices comma is not shown on the numerical keyboard (or requires multiple pressing of a dot button)

Here is my workaround solution, which solves the mentioned problems and lets user typing '.' and ',', but in EditText he will see the only decimal separator which corresponds to current locale:

editText.apply { addTextChangedListener(DoubleTextChangedListener(this)) }

And the text watcher:

  open class DoubleTextChangedListener(private val et: EditText) : TextWatcher {

    init {
        et.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
        et.keyListener = DigitsKeyListener.getInstance("0123456789.,")
    }

    private val separator = DecimalFormatSymbols.getInstance().decimalSeparator

    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
        //empty
    }

    @CallSuper
    override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
        et.run {
            removeTextChangedListener(this@DoubleTextChangedListener)
            val formatted = toLocalizedDecimal(s.toString(), separator)
            setText(formatted)
            setSelection(formatted.length)
            addTextChangedListener(this@DoubleTextChangedListener)
        }
    }

    override fun afterTextChanged(s: Editable?) {
        // empty
    }

    /**
     * Formats input to a decimal. Leaves the only separator (or none), which matches [separator].
     * Examples:
     * 1. [s]="12.12", [separator]=',' -> result= "12,12"
     * 2. [s]="12.12", [separator]='.' -> result= "12.12"
     * 4. [s]="12,12", [separator]='.' -> result= "12.12"
     * 5. [s]="12,12,,..,,,,,34..,", [separator]=',' -> result= "12,1234"
     * 6. [s]="12.12,,..,,,,,34..,", [separator]='.' -> result= "12.1234"
     * 7. [s]="5" -> result= "5"
     */
    private fun toLocalizedDecimal(s: String, separator: Char): String {
        val cleared = s.replace(",", ".")
        val splitted = cleared.split('.').filter { it.isNotBlank() }
        return when (splitted.size) {
            0 -> s
            1 -> cleared.replace('.', separator).replaceAfter(separator, "")
            2 -> splitted.joinToString(separator.toString())
            else -> splitted[0]
                    .plus(separator)
                    .plus(splitted.subList(1, splitted.size - 1).joinToString(""))
        }
    }
}
查看更多
手持菜刀,她持情操
7楼-- · 2019-01-03 09:49

A workaround (until Google fix this bug) is to use an EditText with android:inputType="numberDecimal" and android:digits="0123456789.,".

Then add a TextChangedListener to the EditText with the following afterTextChanged:

public void afterTextChanged(Editable s) {
    double doubleValue = 0;
    if (s != null) {
        try {
            doubleValue = Double.parseDouble(s.toString().replace(',', '.'));
        } catch (NumberFormatException e) {
            //Error
        }
    }
    //Do something with doubleValue
}
查看更多
登录 后发表回答