104 votes

Meilleure façon de formater la saisie de devise dans un editText ?

J'ai un editText, la valeur de départ est de 0,00 $. Lorsque vous appuyez sur 1, cela change à 0,01 $. Appuyez sur 4, cela passe à 0,14 $. Appuyez sur 8, 1,48 $. Appuyez sur la touche de suppression, 0,14 $, etc.

Cela fonctionne, le problème est que si quelqu'un positionne manuellement le curseur, des problèmes surviennent dans le formatage. S'ils suppriment le point décimal, il ne reviendra pas. S'ils placent le curseur devant le point décimal et saisissent 2, il affichera 02,00 $ au lieu de 2,00 $. S'ils essaient de supprimer le $, cela supprimera un chiffre à la place, par exemple.

Voici le code que j'utilise, je serais reconnaissant pour toutes suggestions.

mEditPrice.setRawInputType(Configuration.KEYBOARD_12KEY);
    public void priceClick(View view) {
    mEditPrice.addTextChangedListener(new TextWatcher(){
        DecimalFormat dec = new DecimalFormat("0.00");
        @Override
        public void afterTextChanged(Editable arg0) {
        }
        @Override
        public void beforeTextChanged(CharSequence s, int start,
                int count, int after) {
        }
        @Override
        public void onTextChanged(CharSequence s, int start,
                int before, int count) {
            if(!s.toString().matches("^\\$(\\d{1,3}(\\,\\d{3})*|(\\d+))(\\.\\d{2})?$"))
            {
                String userInput= ""+s.toString().replaceAll("[^\\d]", "");
                if (userInput.length() > 0) {
                    Float in=Float.parseFloat(userInput);
                    float percen = in/100;
                    mEditPrice.setText("$"+dec.format(percen));
                    mEditPrice.setSelection(mEditPrice.getText().length());
                }
            }
        }
    });

2voto

Fernando Points 21

Pour moi, ça a fonctionné comme ça

 public void onTextChanged(CharSequence s, int start,
                    int before, int count) {
                if(!s.toString().matches("^\\$(\\d{1,3}(\\,\\d{3})*|(\\d+))(\\.\\d{2})?$"))
                {
                    String userInput= ""+s.toString().replaceAll("[^\\d]", "");
                    if (userInput.length() > 2) {
                        Float in=Float.parseFloat(userInput);
                        price = Math.round(in); // juste pour obtenir un entier
                        //float percen = in/100;
                        String first, last;
                        first = userInput.substring(0, userInput.length()-2);
                        last = userInput.substring(userInput.length()-2);
                        edEx1.setText("$"+first+"."+last);
                        Log.e(MainActivity.class.toString(), "premier: "+first + " dernier:"+last);
                        edEx1.setSelection(edEx1.getText().length());
                    }
                }
            }

2voto

Mussa Points 764

Il est préférable d'utiliser l'interface InputFilter. Beaucoup plus facile de gérer tous types d'entrées en utilisant des expressions régulières. Ma solution pour le format d'entrée de devise :

public class CurrencyFormatInputFilter implements InputFilter {

Pattern mPattern = Pattern.compile("(0|[1-9]+[0-9]*)(\\.[0-9]{1,2})?");

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

String result = 
        dest.subSequence(0, dstart)
        + source.toString() 
        + dest.subSequence(dend, dest.length());

Matcher matcher = mPattern.matcher(result);

if (!matcher.matches()) return dest.subSequence(dstart, dend);

return null;
}
}

Valide : 0.00, 0.0, 10.00, 111.1
Invalide : 0, 0.000, 111, 10, 010.00, 01.0

Comment utiliser :

editText.setFilters(new InputFilter[] {new CurrencyFormatInputFilter()});

1voto

Nathan Leigh Points 11

J'ai utilisé ceci pour permettre à l'utilisateur d'entrer la devise et de la convertir de chaîne en entier pour la stocker dans la base de données et la reconvertir de entier en chaîne à nouveau

https://github.com/nleigh/Restaurant/blob/master/Restaurant/src/uk/co/nathanleigh/restaurant/CurrencyFormat.java

1voto

sagits Points 188

Si votre champ de devise json est de type nombre (et non pas une chaîne de caractères) il peut être de 3.1, 3.15 ou simplement 3. Car json arrondit automatiquement les champs numériques.

Dans ce cas, vous devrez peut-être l'arrondir pour un affichage correct (et pour pouvoir utiliser un masque sur un champ d'entrée plus tard):

    NumberFormat nf = NumberFormat.getCurrencyInstance();

    float value = 200 // il peut être 200, 200.3 ou 200.37, BigDecimal s'en chargera
    BigDecimal valueAsBD = BigDecimal.valueOf(value);
    valueAsBD.setScale(2, BigDecimal.ROUND_HALF_UP);

    String formated = nf.format(valueAsBD);

Pourquoi est-ce nécessaire?

Toutes les réponses indiquent qu'il faut supprimer les symboles de devise lors de la frappe en supposant que vous recevez les cents et donc le formatage des dollars + cents / 100 = dollar, cents. Mais si votre champ de devise json est un type nombre (et non pas une chaîne de caractères) il arrondira vos cents, ils peuvent être 3, 3.1 ou 3.15.

1voto

Abtin Gramian Points 730

Après avoir consulté la plupart des messages sur StackOverflow sur les différentes façons d'y parvenir en utilisant un TextWatcher, InputFilter, ou une bibliothèque comme CurrencyEditText, j'ai opté pour cette solution simple en utilisant un OnFocusChangeListener.

La logique est de convertir le EditText en nombre lorsqu'il est en focus et de le reformater lorsqu'il perd le focus.

amount.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View view, boolean hasFocus) {
            Number numberAmount = 0f;
            try {
                numberAmount = Float.valueOf(amount.getText().toString());
            } catch (NumberFormatException e1) {
                e1.printStackTrace();
                try {
                    numberAmount = NumberFormat.getCurrencyInstance().parse(amount.getText().toString());
                } catch (ParseException e2) {
                    e2.printStackTrace();
                }
            }
            if (hasFocus) {
                amount.setText(numberAmount.toString());
            } else {
                amount.setText(NumberFormat.getCurrencyInstance().format(numberAmount));
            }
        }
    });

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