Я хочу создать и EditText
со следующими функциями:
- Он должен принимать только целые числа и числа с плавающей запятой с определенными десятичными точками. (Скажем, две десятичные точки, такие как
23.45
).
- Когда пользователь вводит число,
TextWatcher
должен немедленно поставить определенный символ или строку в конце текста (как суффикс), разделенные пробелом (например, 23.46 $
).
- Пользователь не может удалить суффикс. Даже если он попытается, курсор должен идти до конца числа. («Конец числа» означает перед суффиксом и пробелом между числами и суффиксом. Например, когда я пытаюсь удалить
$
из 23.46 $|
, это должно быть похоже на 23.46| $
, где |
- курсор и ничего следует удалить).
- Точку (или запятую) можно удалить.
- [Необязательно] Числа должны быть сгруппированы, когда длина больше. (Как
12 232 546.45 $
. Три числа вместе).
- Нет ведущей точки или более одного нуля
Как я могу это сделать?
Было бы очень полезно для того, кто хочет использовать EditText
, как это, так как это очень распространено.
Ниже вы можете увидеть более четкое изображение.
То, что я попробовал, ниже, но это только для целого числа:
public class AmountTextWatcher implements TextWatcher {
private static final String TAG = "VisaAmountTextWatcher";
private static final String USD_MARK = " $";
private DecimalFormat decimalFormat;
private DecimalFormat dfnd;
private EditText editText;
private TextView textView;
private int minAmount;
private int maxAmount;
private double currencyRate;
public VisaAmountTextWatcher(EditText editText, TextView textView, int minAmount, int maxAmount, double currencyRate){
DecimalFormatSymbols otherSymbols = new DecimalFormatSymbols(new Locale("ru"));
otherSymbols.setDecimalSeparator(',');
otherSymbols.setGroupingSeparator(' ');
decimalFormat = new DecimalFormat("#,###", otherSymbols);
decimalFormat.setDecimalSeparatorAlwaysShown(true);
dfnd = new DecimalFormat("#,###", otherSymbols);
this.editText = editText;
this.textView = textView;
this.minAmount = minAmount;
this.maxAmount = maxAmount;
this.currencyRate = currencyRate;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@SuppressLint("DefaultLocale")
@Override
public void afterTextChanged(Editable s) {
editText.removeTextChangedListener(this);
String changedString = editText.getText().toString().replaceAll("[^0-9]", "");
try {
String error = "";
//s is with blank space(s)
String summaWithoutSpace = s.toString().replaceAll("[^0-9]", "");
if (textView != null) {
String value = changedString.replaceAll("\\s", "");
int summaInCents = value.isEmpty() ? 0 : Integer.parseInt(value);
double summaInUsd = FormatUtils.cent2usd(summaInCents);
if (summaInUsd < minAmount) {
error = String.format("%s: %d %s", editText.getContext().getString(R.string.min_amount_limit), minAmount, editText.getContext().getString(R.string.usd));
} else if (summaInUsd > maxAmount) {
error = String.format("%s: %s %s", editText.getContext().getString(R.string.max_amount_limit), FormatUtils.getFormatSum("" + maxAmount), editText.getContext().getString(R.string.usd));
}
textView.setText(ViewUtils.group(summaInUsd * currencyRate));
}
int newCursorPos;
if(summaWithoutSpace.isEmpty()){
editText.setText("");
newCursorPos = 0;
}
else {
Number actualNumber = decimalFormat.parse(summaWithoutSpace);
String formattedString = dfnd.format(actualNumber) + USD_MARK;
editText.setText(formattedString);
newCursorPos = formattedString.length() - USD_MARK.length();
}
editText.setSelection(newCursorPos);
if (!error.equals("")) {
editText.setError(error);
}
} catch (NumberFormatException | ParseException e) {
// do nothing?
Log.e(TAG, "", e);
}
editText.addTextChangedListener(this);
}
}