web-dev-qa-db-fra.com

Comment ajouter automatiquement des milliers de séparateurs lorsque le nombre est entré dans EditText

En créant une application de conversion, je veux configurer EditText pour que, lorsque l'utilisateur saisit le nombre à convertir, un séparateur de milliers (,) soit ajouté automatiquement en temps réel au nombre incrémenté de 3 chiffres .... .000, millions, milliards, etc., et quand effacé en dessous de 4 chiffres, le nombre redevient normal Toute aide? Merci.

43
Asiimwe

Vous pouvez utiliser String.format() dans une TextWatcher . La virgule dans le spécificateur de format fait l'affaire.

Cela ne fonctionne pas pour les entrées en virgule flottante. Et veillez à ne pas définir de boucle infinie avec TextWatcher.

public void afterTextChanged(Editable view) {
    String s = null;
    try {
        // The comma in the format specifier does the trick
        s = String.format("%,d", Long.parseLong(view.toString()));
    } catch (NumberFormatException e) {
    }
    // Set s back to the view after temporarily removing the text change listener
}
34
Dheeraj V.S.

_ {Le problème enfin résolu} _

Même si c'est trop tard, répondez. J'ai beaucoup cherché à accomplir la tâche pour obtenir le résultat approprié, mais je ne pouvais pas. J'ai donc finalement résolu le problème que nous recherchions et fourni cette réponse aux utilisateurs de Google pour leur permettre de gagner du temps.

Fonctions des codes suivants

  1. Met le séparateur de milliers dans EditText au fur et à mesure que le texte change.

  2. ajoute 0. automatiquement lorsque vous appuyez sur le point (.) au début.

  3. Ignore la saisie de 0 au début.

Il suffit de copier la classe suivante Nommée 

NumberTextWatcherForThousand qui implémenteTextWatcher

import Android.text.Editable;
import Android.text.TextWatcher;
import Android.widget.EditText;
import Java.util.StringTokenizer;

/**
 * Created by skb on 12/14/2015.
 */
public class NumberTextWatcherForThousand implements TextWatcher {

    EditText editText;


    public NumberTextWatcherForThousand(EditText editText) {
        this.editText = editText;


    }

    @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) {
        try
        {
            editText.removeTextChangedListener(this);
            String value = editText.getText().toString();


            if (value != null && !value.equals(""))
            {

                if(value.startsWith(".")){
                    editText.setText("0.");
                }
                if(value.startsWith("0") && !value.startsWith("0.")){
                    editText.setText("");

                }


                String str = editText.getText().toString().replaceAll(",", "");
                if (!value.equals(""))
                editText.setText(getDecimalFormattedString(str));
                editText.setSelection(editText.getText().toString().length());
            }
            editText.addTextChangedListener(this);
            return;
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            editText.addTextChangedListener(this);
        }

    }

    public static String getDecimalFormattedString(String value)
    {
        StringTokenizer lst = new StringTokenizer(value, ".");
        String str1 = value;
        String str2 = "";
        if (lst.countTokens() > 1)
        {
            str1 = lst.nextToken();
            str2 = lst.nextToken();
        }
        String str3 = "";
        int i = 0;
        int j = -1 + str1.length();
        if (str1.charAt( -1 + str1.length()) == '.')
        {
            j--;
            str3 = ".";
        }
        for (int k = j;; k--)
        {
            if (k < 0)
            {
                if (str2.length() > 0)
                    str3 = str3 + "." + str2;
                return str3;
            }
            if (i == 3)
            {
                str3 = "," + str3;
                i = 0;
            }
            str3 = str1.charAt(k) + str3;
            i++;
        }

    }

    public static String trimCommaOfString(String string) {
//        String returnString;
        if(string.contains(",")){
            return string.replace(",","");}
        else {
            return string;
        }

    }
}

_ {Utilisez cette classe sur votre EditText comme suit} _ 

editText.addTextChangedListener(new NumberTextWatcherForThousand(editText));

Pour obtenir une entrée en texte double simple

Utilisez la méthode trimCommaOfString de la même classe comme ceci

NumberTextWatcherForThousand.trimCommaOfString(editText.getText().toString())

Git

43
Shree Krishna
  public static String doubleToStringNoDecimal(double d) {
        DecimalFormat formatter = (DecimalFormat) NumberFormat.getInstance(Locale.US);;
        formatter .applyPattern("#,###");
        return formatter.format(d);
    }
24
user2261183

Cette exemple d'application déconstruit clairement les numéros de formatage.

Pour résumer le lien ci-dessus, utilisez une TextWatcher et dans la méthode afterTextChanged() formatez la vue EditText avec la logique suivante:

@Override
public void afterTextChanged(Editable s) {
    editText.removeTextChangedListener(this);

    try {
        String originalString = s.toString();

        Long longval;
        if (originalString.contains(",")) {
            originalString = originalString.replaceAll(",", "");
        }
        longval = Long.parseLong(originalString);

        DecimalFormat formatter = (DecimalFormat) NumberFormat.getInstance(Locale.US);
        formatter.applyPattern("#,###,###,###");
        String formattedString = formatter.format(longval);

        //setting text after format to EditText
        editText.setText(formattedString);
        editText.setSelection(editText.getText().length());
    } catch (NumberFormatException nfe) {
        nfe.printStackTrace();
    }

    editText.addTextChangedListener(this);
}
3
Adam Hurwitz

Je sais que je suis très en retard à la fête mais cela peut être très utile pour les futurs utilisateurs. Ma réponse est une extension de la réponse de Shree Krishna .

Améliorations:

  1. Des milliers de séparateurs et de marqueurs décimaux tiennent compte des paramètres régionaux, c’est-à-dire qu’ils sont utilisés conformément à la variable Locale du périphérique.
  2. La position du curseur ne change pas après la suppression ou l'ajout d'éléments au milieu également (dans sa réponse, le curseur a été réinitialisé à la fin).
  3. La qualité globale du code a été améliorée, notamment la méthode getDecimalFormattedString.

Code: 

    import Android.text.Editable;
    import Android.text.TextWatcher;
    import Android.widget.EditText;

    import Java.text.DecimalFormat;


    /**
     * Created by srv_twry on 4/12/17.
     * Source: https://stackoverflow.com/a/34265406/137744
     * The custom TextWatcher that automatically adds thousand separators in EditText.
     */

    public class ThousandSeparatorTextWatcher implements TextWatcher {

        private DecimalFormat df;
        private EditText editText;
        private static String thousandSeparator;
        private static String decimalMarker;
        private int cursorPosition;

        public ThousandSeparatorTextWatcher(EditText editText) {
            this.editText = editText;
            df = new DecimalFormat("#,###.##");
            df.setDecimalSeparatorAlwaysShown(true);
            thousandSeparator = Character.toString(df.getDecimalFormatSymbols().getGroupingSeparator());
            decimalMarker = Character.toString(df.getDecimalFormatSymbols().getDecimalSeparator());
        }

        @Override
        public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
            cursorPosition = editText.getText().toString().length() - editText.getSelectionStart();
        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}

        @Override
        public void afterTextChanged(Editable s) {
            try {
                editText.removeTextChangedListener(this);
                String value = editText.getText().toString();

                if (value != null && !value.equals("")) {
                    if (value.startsWith(decimalMarker)) {
                        String text = "0" + decimalMarker;
                        editText.setText(text);
                    }
                    if (value.startsWith("0") && !value.startsWith("0" + decimalMarker)) {
                        int index = 0;
                        while (index < value.length() && value.charAt(index) == '0') {
                            index++;
                        }
                        String newValue = Character.toString(value.charAt(0));
                        if (index != 0) {
                            newValue = value.charAt(0) + value.substring(index);
                        }
                        editText.setText(newValue);
                    }
                    String str = editText.getText().toString().replaceAll(thousandSeparator, "");
                    if (!value.equals("")) {
                        editText.setText(getDecimalFormattedString(str));
                    }
                    editText.setSelection(editText.getText().toString().length());
                }

                //setting the cursor back to where it was
                editText.setSelection(editText.getText().toString().length() - cursorPosition);
                editText.addTextChangedListener(this);
            } catch (Exception ex) {
                ex.printStackTrace();
                editText.addTextChangedListener(this);
            }
        }

        private static String getDecimalFormattedString(String value) {

            String[] splitValue = value.split("\\.");
            String beforeDecimal = value;
            String afterDecimal = null;
            String finalResult = "";

            if (splitValue.length == 2) {
                beforeDecimal = splitValue[0];
                afterDecimal = splitValue[1];
            }

            int count = 0;
            for (int i = beforeDecimal.length() - 1; i >= 0 ; i--) {
                finalResult = beforeDecimal.charAt(i) + finalResult;
                count++;
                if (count == 3 && i > 0) {
                    finalResult = thousandSeparator + finalResult;
                    count = 0;
                }
            }

            if (afterDecimal != null) {
                finalResult = finalResult + decimalMarker + afterDecimal;
            }

            return finalResult;
        }

        /*
        * Returns the string after removing all the thousands separators.
        * */
        public static String getOriginalString(String string) {
            return string.replace(thousandSeparator,"");
        }
    }
2
srv_twry

Cette solution présente un avantage par rapport aux autres réponses. Par exemple, il garde la position du curseur de l'utilisateur même s'il édite le début ou le milieu du numéro. Les autres solutions font toujours passer le curseur à la fin du nombre. Il gère décimales et nombres entiers, ainsi que les paramètres régionaux utilisant des caractères autres que . pour le séparateur décimal et , pour le séparateur de groupes.

class SeparateThousands(val groupingSeparator: String, val decimalSeparator: String) : TextWatcher {

    private var busy = false

    override fun afterTextChanged(s: Editable?) {
        if (s != null && !busy) {
            busy = true

            var place = 0

            val decimalPointIndex = s.indexOf(decimalSeparator)
            var i = if (decimalPointIndex == -1) {
                s.length - 1
            } else {
                decimalPointIndex - 1
            }
            while (i >= 0) {
                val c = s[i]
                if (c == ',') {
                    s.delete(i, i + 1)
                } else {
                    if (place % 3 == 0 && place != 0) {
                        // insert a comma to the left of every 3rd digit (counting from right to
                        // left) unless it's the leftmost digit
                        s.insert(i + 1, groupingSeparator)
                    }
                    place++
                }
                i--
            }

            busy = false
        }
    }

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

    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
    }
}

Puis en XML:

  <EditText
    Android:id="@+id/myNumberField"
    Android:digits=",.0123456789"
    Android:inputType="numberDecimal"
    .../>

Et enfin inscrivez l'observateur:

findViewById(R.id.myNumberField).addTextChangedListener(
    SeparateThousands(groupingSeparator, decimalSeparator))

Gérer . vs, dans des environnements locaux différents, utilisez groupingSeparator et decimalSeparator, qui peuvent provenir de DecimalFormatSymbols ou de chaînes localisées.

2
vlazzle

Voici ma classe ThousandNumberEditText

public class ThousandNumberEditText extends Android.support.v7.widget.AppCompatEditText {
    // TODO: 14/09/2017 change it if you want 
    private static final int MAX_LENGTH = 20;
    private static final int MAX_DECIMAL = 3;

    public ThousandNumberEditText(Context context) {
        this(context, null);
    }

    public ThousandNumberEditText(Context context, AttributeSet attrs) {
        this(context, attrs, Android.support.v7.appcompat.R.attr.editTextStyle);
    }

    public ThousandNumberEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        addTextChangedListener(new ThousandNumberTextWatcher(this));
        setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
        setFilters(new InputFilter[] { new InputFilter.LengthFilter(MAX_LENGTH) });
        setHint("0"); // TODO: 14/09/2017 change it if you want 
    }

    private static class ThousandNumberTextWatcher implements TextWatcher {

        private EditText mEditText;

        ThousandNumberTextWatcher(EditText editText) {
            mEditText = editText;
        }

        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void afterTextChanged(Editable editable) {
            String originalString = editable.toString();
            String cleanString = originalString.replaceAll("[,]", "");
            if (cleanString.isEmpty()) {
                return;
            }
            String formattedString = getFormatString(cleanString);

            mEditText.removeTextChangedListener(this);
            mEditText.setText(formattedString);
            mEditText.setSelection(mEditText.getText().length());
            mEditText.addTextChangedListener(this);
        }

        /**
         * Return the format string
         */
        private String getFormatString(String cleanString) {
            if (cleanString.contains(".")) {
                return formatDecimal(cleanString);
            } else {
                return formatInteger(cleanString);
            }
        }

        private String formatInteger(String str) {
            BigDecimal parsed = new BigDecimal(str);
            DecimalFormat formatter;
            formatter = new DecimalFormat("#,###");
            return formatter.format(parsed);
        }

        private String formatDecimal(String str) {
            if (str.equals(".")) {
                return ".";
            }
            BigDecimal parsed = new BigDecimal(str);
            DecimalFormat formatter;
            formatter =
                    new DecimalFormat("#,###." + getDecimalPattern(str)); //example patter #,###.00
            return formatter.format(parsed);
        }

        /**
         * It will return suitable pattern for format decimal
         * For example: 10.2 -> return 0 | 10.23 -> return 00 | 10.235 -> return 000
         */
        private String getDecimalPattern(String str) {
            int decimalCount = str.length() - 1 - str.indexOf(".");
            StringBuilder decimalPattern = new StringBuilder();
            for (int i = 0; i < decimalCount && i < MAX_DECIMAL; i++) {
                decimalPattern.append("0");
            }
            return decimalPattern.toString();
        }
    }
}

En utilisant

<.ThousandNumberEditText
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    />
1
Linh

vous pouvez utiliser ce code de nombreuses manières dans votre programme, vous lui donnez une chaîne et il sépare chaque trois de la droite et place de l'espace là-bas.

private String Spacer(String number){
    StringBuilder strB = new StringBuilder();
    strB.append(number);
    int Three = 0;

    for(int i=number.length();i>0;i--){
        Three++;
        if(Three == 3){
            strB.insert(i-1, " ");
            Three = 0;
        }
    }
    return strB.toString();
}// end Spacer()

vous pouvez le changer un peu et l'utiliser sur ontextchangelistener . bonne chance

1
Mohammad Hadi

Je voulais juste que comma soit placé et cela fonctionne pour moi:

String.format("%,.2f", myValue);
0
Zohab Ali

Comme j'avais le même problème, j'ai décidé de trouver une solution

Trouver ma fonction ci-dessous j'espère que cela aide les gens à trouver une solution

securityDeposit.addTextChangedListener(new TextWatcher() {

            @Override
            public void onTextChanged(CharSequence s, int start,
                    int before, int count) {
                // TODO Auto-generated method stub

            }

            @Override
            public void beforeTextChanged(CharSequence s, int start,
                    int before, int count) {
                // TODO Auto-generated method stub

            }

            @Override
            public void afterTextChanged(Editable s) {
                // TODO Auto-generated method stub
                if (s.toString().trim().length() > 0) {
                    int rentValue = Integer.parseInt(s.toString()
                            .replaceAll(",", ""));
                    StringBuffer rentVal = new StringBuffer();
                    if (rentValue > 10000000) {
                        s.clear();
                        s.append("10,000,000");
                    } else {

                        if (s.length() == 4) {
                            char x[] = s.toString().toCharArray();

                            char y[] = new char[x.length + 1];
                            for (int z = 0; z < y.length; z++) {

                                if (z == 1) {
                                    y[1] = ',';

                                } else {
                                    if (z == 0)
                                        y[z] = x[z];
                                    else {
                                        y[z] = x[z - 1];
                                    }
                                }

                            }

                            for (int z = 0; z < y.length; z++) {
                                rentVal = rentVal.append(y[z]);
                            }

                            s.clear();
                            s.append(rentVal);

                        }

                    }
                }

            }
        });
0
user1530779