159 votes

Séparateur décimal virgule (',') avec inputType numberDecimal dans EditText

El inputType numberDecimal en EditText utilise le point . comme séparateur décimal. En Europe, il est courant d'utiliser une virgule. , à la place. Bien que ma langue soit l'allemand, le séparateur décimal est toujours le même. .

Existe-t-il un moyen d'obtenir la virgule comme séparateur décimal ?

1 votes

Ce bug a finalement été corrigé dans Android O : issuetracker.google.com/issues/36907764

0 votes

Ils disent qu'il est réparé mais je ne peux pas confirmer qu'il est réparé ? pouvez-vous ?

114voto

Martin Points 1537

Une solution de contournement (jusqu'à ce que Google corrige ce bogue) consiste à utiliser une balise EditText con android:inputType="numberDecimal" y android:digits="0123456789.," .

Ajoutez ensuite un TextChangedListener à l'EditText avec l'afterTextChanged suivant :

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
}

1 votes

@Zoombie pour la virgule (,) à afficher sur votre clavier dépend de la langue définie sur votre appareil. Si votre entrée est de type numberDecimal et que votre langue est l'anglais (États-Unis), elle s'affichera sur les appareils Nexus (référence). Il est possible que les appareils non Nexus ne respectent pas cette règle.

13 votes

Cela fonctionne, mais sachez qu'il laisse passer un texte comme "24,22.55". Vous devrez peut-être ajouter une validation supplémentaire pour résoudre ce problème !

9 votes

Est-ce toujours la voie à suivre ?

17voto

user1269737 Points 175

Code suivant Masque de devise pour EditText ($ 123,125.155)

Mise en page Xml

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

16voto

EricLarch Points 2353

Il s'agit d'un bug connu dans le SDK Android. La seule solution de contournement est de créer votre propre clavier logiciel. Vous pouvez trouver un exemple d'implémentation aquí .

18 votes

Y a-t-il des nouvelles après quatre ans ?

0 votes

Je rencontre également ce problème dans Xamarin.Forms. La culture est {se-SV} et le pavé numérique affiche les chiffres "," (séparateur décimal) et ".". (séparateur de groupes de milliers) mais lorsque l'on appuie sur "," rien n'est saisi dans le champ de texte et aucun événement n'est généré.

0 votes

Je peux confirmer que le bug existe toujours.

6voto

JesperB Points 1804

La réponse de Martin ne fonctionnera pas si vous instanciez l'EditText de manière programmatique. J'ai modifié le fichier inclus DigitsKeyListener de l'API 14 pour permettre l'utilisation de la virgule et du point comme séparateur décimal.

Pour l'utiliser, appelez setKeyListener() sur le EditText par exemple

// Don't allow for signed input (minus), but allow for decimal points
editText.setKeyListener( new MyDigitsKeyListener( false, true ) );

Cependant, vous devez toujours utiliser l'astuce de Martin dans la rubrique TextChangedListener où vous remplacez les virgules par des points

import android.text.InputType;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.method.NumberKeyListener;
import android.view.KeyEvent;

class MyDigitsKeyListener extends NumberKeyListener {

    /**
     * The characters that are used.
     *
     * @see KeyEvent#getMatch
     * @see #getAcceptedChars
     */
    private static final char[][] CHARACTERS = new char[][] {
        new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' },
        new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-' },
        new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', ',' },
        new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '.', ',' },
    };

    private char[] mAccepted;
    private boolean mSign;
    private boolean mDecimal;

    private static final int SIGN = 1;
    private static final int DECIMAL = 2;

    private static MyDigitsKeyListener[] sInstance = new MyDigitsKeyListener[4];

    @Override
    protected char[] getAcceptedChars() {
        return mAccepted;
    }

    /**
     * Allocates a DigitsKeyListener that accepts the digits 0 through 9.
     */
    public MyDigitsKeyListener() {
        this(false, false);
    }

    /**
     * Allocates a DigitsKeyListener that accepts the digits 0 through 9,
     * plus the minus sign (only at the beginning) and/or decimal point
     * (only one per field) if specified.
     */
    public MyDigitsKeyListener(boolean sign, boolean decimal) {
        mSign = sign;
        mDecimal = decimal;

        int kind = (sign ? SIGN : 0) | (decimal ? DECIMAL : 0);
        mAccepted = CHARACTERS[kind];
    }

    /**
     * Returns a DigitsKeyListener that accepts the digits 0 through 9.
     */
    public static MyDigitsKeyListener getInstance() {
        return getInstance(false, false);
    }

    /**
     * Returns a DigitsKeyListener that accepts the digits 0 through 9,
     * plus the minus sign (only at the beginning) and/or decimal point
     * (only one per field) if specified.
     */
    public static MyDigitsKeyListener getInstance(boolean sign, boolean decimal) {
        int kind = (sign ? SIGN : 0) | (decimal ? DECIMAL : 0);

        if (sInstance[kind] != null)
            return sInstance[kind];

        sInstance[kind] = new MyDigitsKeyListener(sign, decimal);
        return sInstance[kind];
    }

    /**
     * Returns a DigitsKeyListener that accepts only the characters
     * that appear in the specified String.  Note that not all characters
     * may be available on every keyboard.
     */
    public static MyDigitsKeyListener getInstance(String accepted) {
        // TODO: do we need a cache of these to avoid allocating?

        MyDigitsKeyListener dim = new MyDigitsKeyListener();

        dim.mAccepted = new char[accepted.length()];
        accepted.getChars(0, accepted.length(), dim.mAccepted, 0);

        return dim;
    }

    public int getInputType() {
        int contentType = InputType.TYPE_CLASS_NUMBER;
        if (mSign) {
            contentType |= InputType.TYPE_NUMBER_FLAG_SIGNED;
        }
        if (mDecimal) {
            contentType |= InputType.TYPE_NUMBER_FLAG_DECIMAL;
        }
        return contentType;
    }

    @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 (mSign == false && mDecimal == false) {
            return out;
        }

        if (out != null) {
            source = out;
            start = 0;
            end = out.length();
        }

        int sign = -1;
        int decimal = -1;
        int dlen = dest.length();

        /*
         * Find out if the existing text has '-' or '.' characters.
         */

        for (int i = 0; i < dstart; i++) {
            char c = dest.charAt(i);

            if (c == '-') {
                sign = i;
            } else if (c == '.' || c == ',') {
                decimal = i;
            }
        }
        for (int i = dend; i < dlen; i++) {
            char c = dest.charAt(i);

            if (c == '-') {
                return "";    // Nothing can be inserted in front of a '-'.
            } else if (c == '.' ||  c == ',') {
                decimal = i;
            }
        }

        /*
         * If it does, we must strip them out from the source.
         * In addition, '-' must be the very first character,
         * and nothing can be inserted before an existing '-'.
         * Go in reverse order so the offsets are stable.
         */

        SpannableStringBuilder stripped = null;

        for (int i = end - 1; i >= start; i--) {
            char c = source.charAt(i);
            boolean strip = false;

            if (c == '-') {
                if (i != start || dstart != 0) {
                    strip = true;
                } else if (sign >= 0) {
                    strip = true;
                } else {
                    sign = i;
                }
            } else if (c == '.' || c == ',') {
                if (decimal >= 0) {
                    strip = true;
                } else {
                    decimal = i;
                }
            }

            if (strip) {
                if (end == start + 1) {
                    return "";  // Only one character, and it was stripped.
                }

                if (stripped == null) {
                    stripped = new SpannableStringBuilder(source, start, end);
                }

                stripped.delete(i - start, i + 1 - start);
            }
        }

        if (stripped != null) {
            return stripped;
        } else if (out != null) {
            return out;
        } else {
            return null;
        }
    }
}

0 votes

Du doc : KeyListener ne doit être utilisé que dans les cas où une application possède son propre clavier à l'écran et souhaite également traiter les événements du clavier dur pour y correspondre. developer.Android.com/reference/Android/text/method/

2voto

Ludwo Points 3166

Pour les solutions Mono(Droid) :

decimal decimalValue = decimal.Parse(input.Text.Replace(",", ".") , CultureInfo.InvariantCulture);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X