Voici mon CurrencyEditText
personnalisé
import android.content.Context;import android.graphics.Rect;import android.text.Editable; import android.text.InputFilter; import android.text.InputType; import android.text.TextWatcher; import android.util.AttributeSet; import android.widget.EditText; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.Locale;
/**
* Une note
* Utilisez toujours la locale US au lieu de la valeur par défaut pour que DecimalFormat fonctionne bien dans toutes les langues
*/
public class CurrencyEditText extends android.support.v7.widget.AppCompatEditText {
private static String préfixe = "VND ";
private static final int LONGUEUR_MAX = 20;
private static final int MAX_DECIMAL = 3;
private CurrencyTextWatcher currencyTextWatcher = new CurrencyTextWatcher(this, préfixe);
public CurrencyEditText(Context context) {
this(context, null);
}
public CurrencyEditText(Context context, AttributeSet attrs) {
this(context, attrs, android.support.v7.appcompat.R.attr.editTextStyle);
}
public CurrencyEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
this.setHint(préfixe);
this.setFilters(new InputFilter[] { new InputFilter.LengthFilter(LONGUEUR_MAX) });
}
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
if (focused) {
this.addTextChangedListener(currencyTextWatcher);
} else {
this.removeTextChangedListener(currencyTextWatcher);
}
handleCaseCurrencyEmpty(focused);
}
/**
* Lorsque la devise est vide
* + Lorsque EditText est en focus, définissez le texte par défaut = préfixe (ex : VND)
* + Lorsque EditText perd le focus, définissez le texte par défaut = "", EditText affichera le hint (ex : VND)
*/
private void handleCaseCurrencyEmpty(boolean focused) {
if (focused) {
if (getText().toString().isEmpty()) {
setText(préfixe);
}
} else {
if (getText().toString().equals(préfixe)) {
setText("");
}
}
}
private static class CurrencyTextWatcher implements TextWatcher {
private final EditText editText;
private String previousCleanString;
private String préfixe;
CurrencyTextWatcher(EditText editText, String préfixe) {
this.editText = editText;
this.préfixe = préfixe;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// ne rien faire
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// ne rien faire
}
@Override
public void afterTextChanged(Editable editable) {
String str = editable.toString();
if (str.length() < préfixe.length()) {
editText.setText(préfixe);
editText.setSelection(préfixe.length());
return;
}
if (str.equals(préfixe)) {
return;
}
// cleanString est la chaîne qui ne contient pas de préfixe et de virgules
String cleanString = str.replace(préfixe, "").replaceAll("[,]", "");
// pour éviter l'appel récursif de afterTextChanged
if (cleanString.equals(previousCleanString) || cleanString.isEmpty()) {
return;
}
previousCleanString = cleanString;
String formattedString;
if (cleanString.contains(".")) {
formattedString = formatDecimal(cleanString);
} else {
formattedString = formatInteger(cleanString);
}
editText.removeTextChangedListener(this); // Supprimer le listener
editText.setText(formattedString);
handleSelection();
editText.addTextChangedListener(this); // Ajouter à nouveau le listener
}
private String formatInteger(String str) {
BigDecimal parsed = new BigDecimal(str);
DecimalFormat formatter =
new DecimalFormat(préfixe + "#,###", new DecimalFormatSymbols(Locale.US));
return formatter.format(parsed);
}
private String formatDecimal(String str) {
if (str.equals(".")) {
return préfixe + ".";
}
BigDecimal parsed = new BigDecimal(str);
// modèle exemple VND #,###.00
DecimalFormat formatter = new DecimalFormat(préfixe + "#,###." + getDecimalPattern(str),
new DecimalFormatSymbols(Locale.US));
formatter.setRoundingMode(RoundingMode.DOWN);
return formatter.format(parsed);
}
/**
* Cela renverra un motif approprié pour formater le décimal
* Par exemple: 10.2 -> retourne 0 | 10.23 -> retourne 00, | 10.235 -> retourne 000
*/
private String getDecimalPattern(String str) {
int decimalCount = str.length() - str.indexOf(".") - 1;
StringBuilder decimalPattern = new StringBuilder();
for (int i = 0; i < decimalCount && i < MAX_DECIMAL; i++) {
decimalPattern.append("0");
}
return decimalPattern.toString();
}
private void handleSelection() {
if (editText.getText().length() <= LONGUEUR_MAX) {
editText.setSelection(editText.getText().length());
} else {
editText.setSelection(LONGUEUR_MAX);
}
}
}
}
Utilisez-le dans XML comme
<...CurrencyEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
Vous devriez modifier les 2 constantes ci-dessous pour convenir à votre projet
private static String préfixe = "VND ";
private static final int MAX_DECIMAL = 3;
Démo sur github