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

133

Le inputType numberDecimalin EditTextutilise le point '.' comme séparateur décimal. En Europe, il est courant d'utiliser une virgule «,» à la place. Même si mes paramètres régionaux sont définis en allemand, le séparateur décimal est toujours le '.'

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

mseo
la source
1
ce bug a finalement été corrigé dans Android O: issuetracker.google.com/issues/36907764
Lovis
ils disent que c'est corrigé mais je ne peux pas le confirmer? peut tu?
sebastian
5
Je peux confirmer que ce n'est PAS corrigé, du moins sur mon Nexus 4 sous Android 8.1 (alias LineageOS 15.1). Avec Settings-> Language réglé sur French (France), un EditText avec android: inputType = "numberDecimal" propose le séparateur ',' (virgule) mais refuse toujours d'accepter la virgule. L'offre '.' (point décimal) est accepté. Cela fait plus de 9 ans que ce bogue a été signalé pour la première fois. Est-ce une sorte de record? Boiteux.
pete du

Réponses:

105

Une solution de contournement (jusqu'à ce que Google corrige ce bogue) consiste à utiliser un EditTextavec android:inputType="numberDecimal"et android:digits="0123456789.,".

Ajoutez ensuite un TextChangedListener à EditText avec le 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
}
Martin
la source
1
@Zoombie pour que la virgule (,) s'affiche 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 cela
HCPL
11
Cela fonctionne, mais sachez que cela laisse passer un texte comme "24,22.55". Vous devrez peut-être ajouter une validation supplémentaire pour résoudre ce problème!
dimsuz
8
Est-ce toujours la voie à suivre?
Willi Mentzel
Mieux encore, utilisez char localizedSeparator = DecimalFormatSymbols.getInstance (). GetDecimalSeparator (); localizedFloatString = localizedFloatString.replace ('.', localizedSeparator);
southerton
4
On dirait que c'est juste échanger un bogue pour un autre. Comme implémenté ci-dessus, cela fonctionnera pour les paramètres régionaux qui utilisent, au lieu de. au prix de l'inverse qui est plus courant dans le monde. Le tweak de @ sudherton aide avec cela, mais vos utilisateurs peuvent être surpris lorsqu'ils atteignent un. et faire apparaître un, dans l'entrée.
Nick
30

Une variation sur les solutions 'digit' proposées ici:

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

Prise en compte du séparateur de paramètres régionaux.

dstibbe
la source
C'est la réponse la plus claire à la question initiale. Merci
peter.bartos
Placez ceci dans onCreate (), c'est la voie à suivre, à mon humble avis.
TechNyquist
6
J'aime ça, mais attention ... il y a des claviers qui ne se soucient pas des paramètres régionaux de l'utilisateur, donc l'utilisateur qui n'a pas la clé ,dans son clavier. Exemples: clavier Samsung (KitKat).
Brais Gabin
2
Cela permettra la duplication des séparateurs décimaux. Voir la réponse ci-dessous pour le gérer: stackoverflow.com/a/45384821/6138589
Esdras Lopez
19

Masque de devise de code suivant 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;
        }
    });
user1269737
la source
16

Il s'agit d'un bogue connu dans le SDK Android. La seule solution de contournement consiste à créer votre propre clavier virtuel. Vous pouvez trouver un exemple d'implémentation ici .

EricLarch
la source
15
Y a-t-il des nouvelles après quatre ans?
Antonio Sesto
Vivre cela également dans Xamarin.Forms. La culture est {se-SV} et le pavé numérique affiche bot "," (séparateur décimal) et "." (séparateur de milliers de groupes) mais en appuyant sur "," rien n'est entré dans le champ de texte et aucun événement n'est
déclenché
Je peux confirmer que le bogue existe toujours.
Lensflare
corrigé dans l'aperçu du développeur Android O
R00We
6

La réponse Martins ne fonctionnera pas si vous instanciez le EditText par programme. Je suis allé de l'avant et j'ai modifié la DigitsKeyListenerclasse incluse de l'API 14 pour permettre à la fois la virgule et le point comme séparateur décimal.

Pour l'utiliser, appelez setKeyListener()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 le TextChangedListenercas 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;
        }
    }
}
JesperB
la source
from 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 de clavier dur pour y correspondre. developer.android.com/reference/android/text/method/…
Loda
6

vous pouvez utiliser ce qui suit pour différents paramètres régionaux

private void localeDecimalInput(final EditText editText){

    DecimalFormat decFormat = (DecimalFormat) DecimalFormat.getInstance(Locale.getDefault());
    DecimalFormatSymbols symbols=decFormat.getDecimalFormatSymbols();
    final String defaultSeperator=Character.toString(symbols.getDecimalSeparator());

    editText.addTextChangedListener(new TextWatcher() {

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

        }

        @Override
        public void afterTextChanged(Editable editable) {
            if(editable.toString().contains(defaultSeperator))
                editText.setKeyListener(DigitsKeyListener.getInstance("0123456789"));
            else
                editText.setKeyListener(DigitsKeyListener.getInstance("0123456789" + defaultSeperator));
        }
    });
}
Ismail
la source
C'est la meilleure solution pour moi, mais il y a des problèmes avec certains téléphones, par exemple Samsung, qui ne montrent pas le "," coma sur le clavier. J'ai donc changé cela pour autoriser à la fois le coma et le point, mais en remplaçant ensuite en fonction de la locale
Riccardo Casatta
5

Vous pouvez utiliser la solution de contournement suivante pour inclure également la virgule comme entrée valide: -

Via XML:

<EditText
    android:inputType="number"
    android:digits="0123456789.," />

Par programme:

EditText input = new EditText(THE_CONTEXT);
input.setKeyListener(DigitsKeyListener.getInstance("0123456789.,"));

De cette façon, le système Android affichera le clavier des chiffres et autorisera la saisie d'une virgule. J'espère que cela répond à la question :)

MiaN KhaLiD
la source
Avec cette solution, lorsque vous appuyez sur ",", mais que le texte de modification affiche "."
Mara Jimenez le
2

Pour les solutions Mono (Droid):

decimal decimalValue = decimal.Parse(input.Text.Replace(",", ".") , CultureInfo.InvariantCulture);
Ludwo
la source
1

Vous pouvez faire ce qui suit:

DecimalFormatSymbols d = DecimalFormatSymbols.getInstance(Locale.getDefault());
input.setFilters(new InputFilter[] { new DecimalDigitsInputFilter(5, 2) });
input.setKeyListener(DigitsKeyListener.getInstance("0123456789" + d.getDecimalSeparator()));

Et puis vous pouvez utiliser un filtre d'entrée:

    public class DecimalDigitsInputFilter implements InputFilter {

Pattern mPattern;

public DecimalDigitsInputFilter(int digitsBeforeZero, int digitsAfterZero) {
    DecimalFormatSymbols d = new DecimalFormatSymbols(Locale.getDefault());
    String s = "\\" + d.getDecimalSeparator();
    mPattern = Pattern.compile("[0-9]{0," + (digitsBeforeZero - 1) + "}+((" + s + "[0-9]{0," + (digitsAfterZero - 1) + "})?)||(" + s + ")?");
}

@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {

    Matcher matcher = mPattern.matcher(dest);
    if (!matcher.matches())
        return "";
    return null;
}

}

Pablo
la source
il pourrait y avoir un espace entre mille et cent, ce modèle refuserait l'entrée formatée
Eric Zhao
1

À mon humble avis, la meilleure approche pour ce problème consiste simplement à utiliser InputFilter. Un bon point essentiel est ici DecimalDigitsInputFilter . Ensuite, vous pouvez simplement:

editText.setInputType(TYPE_NUMBER_FLAG_DECIMAL | TYPE_NUMBER_FLAG_SIGNED | TYPE_CLASS_NUMBER)
editText.setKeyListener(DigitsKeyListener.getInstance("0123456789,.-"))
editText.setFilters(new InputFilter[] {new DecimalDigitsInputFilter(5,2)});
Arkadiusz Cieśliński
la source
Cela a fonctionné comme un charme, merci! (après tant de mauvaises solutions ci-dessus ... :() Mais j'ai une question: Comment puis-je obtenir cette virgule (",") affichée à l'écran et non point (".") car en Hongrie, nous utilisons la virgule comme séparateur décimal .
Abigail La'Fay
1
android: digits = "0123456789", le paramètre peut être ajouté à EditText. De plus, au lieu de renvoyer null dans DecimalDigitsInputFilter, vous pouvez renvoyer source.replace (".", ",") Selon la réponse stackoverflow.com/a/40020731/1510222, il n'y a aucun moyen de masquer le point dans un clavier standard
Arkadiusz Cieśliński
1

pour localiser votre entrée, utilisez:

char sep = DecimalFormatSymbols.getInstance().getDecimalSeparator();

puis ajoutez:

textEdit.setKeyListener(DigitsKeyListener.getInstance("0123456789" + sep));

alors n'oubliez pas de remplacer "," par "." donc Float ou Double peuvent l'analyser sans erreur.

Milos Simic Simo
la source
1
Cette solution permet de saisir plusieurs virgules
Leo Droidcoder
1

Tous les autres articles ici présentaient des lacunes majeures, voici donc une solution qui:

  • Appliquer des virgules ou des points en fonction de la région ne vous permettra pas de taper le contraire.
  • Si le EditText commence par une valeur, il remplace le séparateur correct si nécessaire.

Dans le XML:

<EditText
    ...
    android:inputType="numberDecimal" 
    ... />

Variable de classe:

private boolean isDecimalSeparatorComma = false;

Dans onCreate, recherchez le séparateur utilisé dans la locale actuelle:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    NumberFormat nf = NumberFormat.getInstance();
    if (nf instanceof DecimalFormat) {
        DecimalFormatSymbols sym = ((DecimalFormat) nf).getDecimalFormatSymbols();
        char decSeparator = sym.getDecimalSeparator();
        isDecimalSeparatorComma = Character.toString(decSeparator).equals(",");
    }
}

Aussi onCreate, utilisez ceci pour le mettre à jour si vous chargez dans une valeur actuelle:

// Replace editText with commas or periods as needed for viewing
String editTextValue = getEditTextValue(); // load your current value
if (editTextValue.contains(".") && isDecimalSeparatorComma) {
    editTextValue = editTextValue.replaceAll("\\.",",");
} else if (editTextValue.contains(",") && !isDecimalSeparatorComma) {
    editTextValue = editTextValue.replaceAll(",",".");
}
setEditTextValue(editTextValue); // override your current value

Aussi surCréer, ajouter les auditeurs

editText.addTextChangedListener(editTextWatcher);

if (isDecimalSeparatorComma) {
    editText.setKeyListener(DigitsKeyListener.getInstance("0123456789,"));
} else {
    editText.setKeyListener(DigitsKeyListener.getInstance("0123456789."));
}

editTextWatcher

TextWatcher editTextWatcher = new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) { }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) { }

    @Override
    public void afterTextChanged(Editable s) {
        String editTextValue = s.toString();

        // Count up the number of commas and periods
        Pattern pattern = Pattern.compile("[,.]");
        Matcher matcher = pattern.matcher(editTextValue);
        int count = 0;
        while (matcher.find()) {
            count++;
        }

        // Don't let it put more than one comma or period
        if (count > 1) {
            s.delete(s.length()-1, s.length());
        } else {
            // If there is a comma or period at the end the value hasn't changed so don't update
            if (!editTextValue.endsWith(",") && !editTextValue.endsWith(".")) {
                doSomething()
            }
        }
    }
};

Exemple de doSomething (), conversion en période standard pour la manipulation de données

private void doSomething() {
    try {
        String editTextStr = editText.getText().toString();
        if (isDecimalSeparatorComma) {
            editTextStr = editTextStr.replaceAll(",",".");
        }
        float editTextFloatValue = editTextStr.isEmpty() ?
                0.0f :
                Float.valueOf(editTextStr);

        ... use editTextFloatValue
    } catch (NumberFormatException e) {
        Log.e(TAG, "Error converting String to Double");
    }
}
Elijah Fry
la source
0

Android a un formateur de nombres intégré.

Vous pouvez l'ajouter à votre EditTextpour autoriser les décimales et les virgules: android:inputType="numberDecimal"etandroid:digits="0123456789.,"

Puis quelque part dans votre code, soit lorsque l'utilisateur clique sur Enregistrer, soit après la saisie du texte (utilisez un écouteur).

// Format the number to the appropriate double
try { 
    Number formatted = NumberFormat.getInstance().parse(editText.getText().toString());
    cost = formatted.doubleValue();
} catch (ParseException e) {
    System.out.println("Error parsing cost string " + editText.getText().toString());
    cost = 0.0;
}
Luis
la source
0

J'ai décidé de changer la virgule en point uniquement lors de l'édition. Voici ma solution de contournement délicate et relativement simple:

    editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            EditText editText = (EditText) v; 
            String text = editText.getText().toString();
            if (hasFocus) {
                editText.setText(text.replace(",", "."));
            } else {
                if (!text.isEmpty()) {
                    Double doubleValue = Double.valueOf(text.replace(",", "."));
                    editText.setText(someDecimalFormatter.format(doubleValue));
                }
            }
        }
    });

someDecimalFormatter utilisera une virgule ou un point selon les paramètres régionaux

KaMyLL
la source
0

Je ne sais pas pourquoi vos réponses sont si compliquées. S'il y a un bogue dans le SDK, vous devez le remplacer ou le contourner.

J'ai choisi la deuxième façon de résoudre ce problème. Si vous formatez votre chaîne en tant que Locale.ENGLISH, puis placez-la dans EditText(même sous forme de chaîne vide). Exemple:

String.format(Locale.ENGLISH,"%.6f", yourFloatNumber);

En poursuivant cette solution, vos résultats sont compatibles avec le clavier illustré. Ensuite, les nombres flottants et doubles fonctionnent de manière typique pour les langages de programmation avec un point au lieu de la virgule.

Dominik
la source
0

Ma solution est:

  • Dans l'activité principale:

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

  • Dans un fichier xml: android:imeOptions="flagNoFullscreen" android:inputType="numberDecimal"

et j'ai pris le double dans le editText comme une chaîne.

Lseb
la source
0

Je peux confirmer que les correctifs proposés ne fonctionnent pas sur les IME de Samsung (du moins sur S6 et S9) et peut-être sur LG. Ils affichent toujours un point comme séparateur décimal quelle que soit la localisation. Le passage à l'IME de Google corrige ce problème, mais ce n'est guère une option pour la plupart des développeurs.

Cela n'a pas non plus été corrigé dans Oreo pour ces claviers, car c'est un correctif que Samsung et / ou LG doivent faire et ensuite pousser même sur leurs anciens combinés.

J'ai plutôt forké le projet de clavier numérique et ajouté un mode où il se comporte comme un IME: fork . Consultez l'exemple de projet pour plus de détails. Cela a très bien fonctionné pour moi et est similaire à la plupart des faux IME «saisie de code PIN» que vous voyez dans les applications bancaires.

Exemple de capture d'écran de l'application

Kevin Lire
la source
0

Cela fait plus de 8 ans et je suis surpris, ce problème n'est pas encore résolu ...
J'ai eu du mal avec ce problème simple car la réponse la plus votée de @Martin permet de taper plusieurs séparateurs, c'est-à-dire que l'utilisateur peut taper "12 ,,, ,,, 12,1,, 21,2, "
De plus, le deuxième problème est que sur certains appareils, la virgule n'est pas affichée sur le clavier numérique (ou nécessite une pression multiple sur un bouton à point)

Voici ma solution de contournement, qui résout les problèmes mentionnés et permet à l'utilisateur de taper '.' et ',', mais dans EditText, il verra le seul séparateur décimal qui correspond à la locale actuelle:

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

Et l'observateur de texte:

  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(""))
        }
    }
}
Leo Droidcoder
la source
0

Solution simple, faites un contrôle personnalisé. (ceci est fait dans Xamarin android mais devrait être porté facilement vers java)

public class EditTextDecimalNumber:EditText
{
    readonly string _numberFormatDecimalSeparator;

    public EditTextDecimalNumber(Context context, IAttributeSet attrs) : base(context, attrs)
    {
        InputType = InputTypes.NumberFlagDecimal;
        TextChanged += EditTextDecimalNumber_TextChanged;
        _numberFormatDecimalSeparator = System.Threading.Thread.CurrentThread.CurrentUICulture.NumberFormat.NumberDecimalSeparator;

        KeyListener = DigitsKeyListener.GetInstance($"0123456789{_numberFormatDecimalSeparator}");
    }

    private void EditTextDecimalNumber_TextChanged(object sender, TextChangedEventArgs e)
    {
        int noOfOccurence = this.Text.Count(x => x.ToString() == _numberFormatDecimalSeparator);
        if (noOfOccurence >=2)
        {
            int lastIndexOf = this.Text.LastIndexOf(_numberFormatDecimalSeparator,StringComparison.CurrentCulture);
            if (lastIndexOf!=-1)
            {
                this.Text = this.Text.Substring(0, lastIndexOf);
                this.SetSelection(this.Text.Length);
            }

        }
    }
}
Nicolai
la source
0

Vous pouvez utiliser inputType="phone", mais dans ce cas, vous devrez gérer plusieurs ,ou .être présent, une validation supplémentaire serait donc nécessaire.

jack's medulla oblongata
la source
-1

Je pense que cette solution est moins complexe que les autres écrites ici:

<EditText
    android:inputType="numberDecimal"
    android:digits="0123456789," />

De cette façon, lorsque vous appuyez sur le '.' dans le clavier virtuel, rien ne se passe; seuls les chiffres et les virgules sont autorisés.

Jorge Alcolea Coronel
la source
4
si vous faites cela, vous casserez simplement tous les paramètres régionaux utilisant '.' au lieu.
Nick