Как изменить положение курсора при редактировании поля EditText, отформатированного как валюта США - Android - PullRequest
0 голосов
/ 27 ноября 2018

Я форматирую текстовое поле редактирования в соответствии с форматом американской валюты, где при наборе числа в поле, скажем, «12345678», оно выглядит как «12 345 678».Для этого я использовал TextWatcher и по методу afterTextChanged(...) я форматирую введенный текст как:

@Override
    public void afterTextChanged(Editable editable) {
        String str = editable.toString();
        String number = str.replaceAll("[,]", "");
        if (number.equals(previousNumber) || number.isEmpty()) {
            return;
        }
        previousNumber = number;

        DecimalFormat formatter = new DecimalFormat("#,###.##", new DecimalFormatSymbols(Locale.US));

        String formattedString = formatter.format(number);
        editText.setText(formattedString);
    }

Также я использую onSelectionChanged(...) метод обратного вызова, например:

 @Override
protected void onSelectionChanged(int selStart, int selEnd) {
    this.setSelection(selStart);
}

Но здесь этот selStart не возвращает фактическую длину числа, поскольку исключает число «,» в каждой валюте.Например: для «12 345 678» возвращается число 8 вместо 10. Поэтому я не могу поместить курсор в конец поля.

Ниже приведен код пользовательского EditText, которым я являюсьиспользуя:

public class CurrencyEditText extends AppCompatEditText {
private static final int MAX_LENGTH = 16;
private static final int MAX_DECIMAL_DIGIT = 2;
private static String prefix = "";
private CurrencyTextWatcher currencyTextWatcher = new CurrencyTextWatcher(this, prefix);

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

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

private void handleCaseCurrencyEmpty(boolean focused) {
    if (!focused) {
        if (getText().toString().equals(prefix)) {
            setText("");
        }
    }
}

private static class CurrencyTextWatcher implements TextWatcher {
    private final EditText editText;
    DecimalFormat formatter;
    private String previousNumber;
    private String prefix;
    Context mContext;

    CurrencyTextWatcher(EditText editText, String prefix) {
        this.editText = editText;
        this.prefix = prefix;
        formatter = new DecimalFormat("#,###.##", new DecimalFormatSymbols(Locale.US));
    }

    @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 editable) {
        String str = editable.toString();
        String number = str.replaceAll("[,]", "");
        if (number.equals(previousNumber) || number.isEmpty()) {
            return;
        }
        previousNumber = number;

        String formattedString = prefix + formatNumber(number);
        editText.removeTextChangedListener(this);
        editText.setText(formattedString);
        //handleSelection();
        editText.addTextChangedListener(this);
    }

    private String formatNumber(String number) {
        if (number.contains(".")) {
            return formatDecimal(number);
        }
        return formatInteger(number);
    }

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

    private String formatDecimal(String str) {
        if (str.equals(".")) {
            return "0.";
        }
        BigDecimal parsed = new BigDecimal(str);
        DecimalFormat formatter = new DecimalFormat("#,##0." + getDecimalPattern(str),
                new DecimalFormatSymbols(Locale.US));
        formatter.setRoundingMode(RoundingMode.DOWN);
        return formatter.format(parsed);
    }

    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_DIGIT; i++) {
            decimalPattern.append("0");
        }
        return decimalPattern.toString();
    }

    /*private void handleSelection() {
        if (editText.getText().length() <= MAX_LENGTH) {
            editText.setSelection(editText.getText().length());
        }
    }*/
}

@Override
protected void onSelectionChanged(int selStart, int selEnd) {
    this.setSelection(selStart);
}

}

Я не хочу использовать this.setSelection(lengthOfTheEnteredText), потому что это создало проблему при редактировании поля!В чем может быть причина того, что onSelectionChanged(...) не учитывает число ",", присутствующее в числе?

1 Ответ

0 голосов
/ 27 ноября 2018

После изучения этого вопроса я нашел решение.Где я рассчитываю позицию курсора.Я удалил метод onSelectionChanged(...) из своего кода и обрабатываю выбор в методе afterTextChanged(...).В следующем коде я внес изменения в afterTextChanged(...):

@Override
    public void afterTextChanged(Editable editable) {

        String str = editable.toString();
        String number = str.replaceAll("[,]", "");
        if (number.equals(previousNumber) || number.isEmpty()) {
            return;
        }
        previousNumber = number;

        int startText, endText;
        startText = editText.getText().length();

        int selectionStart = editText.getSelectionStart();

        String formattedString = prefix + formatNumber(number);
        editText.removeTextChangedListener(this);
        editText.setText(formattedString);
        endText = editText.getText().length();

        int selection = (selectionStart + (endText - startText));
        editText.setSelection(selection);

        editText.addTextChangedListener(this);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...