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

0voto

Gal Rom Points 218

Utilisez ce inputType dans votre XML

android:inputType="numberSigned|numberDecimal"

Ajoutez cette belle fonction d'extension en Kotlin :

**
 * Utilisez cette fonction depuis [TextWatcher.afterTextChanged] elle appellera d'abord [AppCompatEditText.removeTextChangedListener]
 * sur le TextWatcher que vous passez, manipulera le texte, puis le réenregistrera après avoir appelé setText.
 *
 * @param fallback La chaîne que nous retournerons si l'utilisateur fait une addition illégale, comme essayer d'ajouter un troisième chiffre après la virgule.
 *                  Il est préférable de garder le fallback comme un membre de la classe dans laquelle EditText réside - et de le stocker dedans
 * @param textWatcher [TextWatcher] Il sera utilisé pour se désinscrire avant de manipuler le texte.
 * @param locale La locale que nous passerons à [NumberFormat.getCurrencyInstance] - elle affectera le symbole de devise. la valeur par défaut est [Locale.US]
 *
 * @return Une chaîne formatée à utiliser dans [AppCompatEditText.setText]
 *
 */
fun AppCompatEditText.formatCurrency(@NonNull fallback: String, @NonNull textWatcher: TextWatcher,
                                     locale: Locale = Locale.US) {

    removeTextChangedListener(textWatcher)

    var original = text.toString()
    if (original.startsWith(".")) {
        // Si l'utilisateur appuie sur la touche '.-' au début du montant - nous obtenons '.' et le transformons en '-'
        setText(original.replaceFirst(".", "-"))
        addTextChangedListener(textWatcher)
        setSelection(text?.length ?: 0)
        return
    }
    val split = original.split(".")
    when (split.size) {
        0 -> {
            setText(fallback)
            addTextChangedListener(textWatcher)
            setSelection(text?.length ?: 0)
            return
        }
        1 -> {
            if (split[0] == "-") {
                setText("-")
                addTextChangedListener(textWatcher)
                setSelection(text?.length ?: 0)
                return
            }
        }
        2 -> {
            if (split[1].length > 2) {
                setText(fallback)
                addTextChangedListener(textWatcher)
                setSelection(text?.length ?: 0)
                return
            }
        }
    }
    // Nous stockons la valeur décimale dans une variable locale
    val decimalSplit = original.split(".")
    // drapeau pour indiquer que nous avons une partie décimale dans la chaîne d'origine.
    val hasDecimal = decimalSplit.size > 1
    if (hasDecimal) {
        original = decimalSplit[0]
    }
    val isNegative = original.startsWith("-")
    val cleanString: String = original.replace("""[$,]""".toRegex(), "")

    val result = if (cleanString.isNotEmpty() && cleanString != "-") {
        val formatString = original.replace("""[-$,.]""".toRegex(), "")
        // Ajouter des virgules et le symbole de devise.
        var result = NumberFormat.getCurrencyInstance(locale).format(formatString.toDouble())
        result = result.split('.')[0]
        if (isNegative) {
            // S'il était négatif, nous devons ajouter le signe moins.
            result = "-${result}"
        }
        if (hasDecimal) {
            // après le formatage, la décimale est omise, nous devons l'ajouter.
            result = "${result}.${decimalSplit[1]}"
        }
        result
    } else {
        original
    }
    setText(result)
    addTextChangedListener(textWatcher)
    setSelection(text?.length ?: 0)
}

Et utilisez-la comme ceci :

class MyCoolClass{

    private var mLastAmount = ""
    ...
    ...

    private fun addTextWatcherToEt() {
            mEtAmount.addTextChangedListener(object : TextWatcher {

                override fun afterTextChanged(s: Editable?) {
                    mEtAmount.formatCurrency(mLastAmount, this)
                    mLastAmount = mEtAmount.text.toString()

                    // Faire plus de choses ici si nécessaire ...
                }

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

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

                }
            })
        }

}

0voto

zihadrizkyef Points 586

Je pense que ce library est meilleure, car :

  1. il supporte l'édition de chiffres au milieu sans déplacer le curseur à la fin
  2. nous pouvons facilement changer le signe de la monnaie
  3. empêche la suppression du signe de la monnaie
  4. supprime automatiquement "0" au début
  5. et d'autres personnalisations

entrez la description de l'image ici

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