提问者:小点点

EditText缓存旧文本


我有以下问题。我有EditText和TextWatcher,它们根据一些规则格式化输入文本。在TextChanged()之后的方法中,我格式化它。然后我有格式化的字符串,我想用格式化的值替换EditText的旧值。接下来我们有两个选项:

    < li >使用EditText.setText() < li >使用Editable.replace()

如果我们使用第一个选项,EditText的工作速度非常慢,并且会丢失符号。但是如果我们使用第二种方法,可编辑不会替换旧文本,而是将新文本附加到旧文本上。

也许有人有类似的问题?

更新:使用可编辑.clear() 然后可编辑.追加() 或插入() 具有类似的效果

代码:

    public static class LoginWatcher implements TextWatcher {

    private EditText target;
    private LoginFilter loginFilter = new LoginFilter();

    private int lastLength;
    private boolean wasPhoneNumber = false;

    private AsYouTypeFormatter formatter;
    private boolean isFormattingStopped;

    public LoginWatcher(OnLoginEnterListener onLoginInputListener, EditText target) {
        listener = onLoginInputListener;
        this.target = target;
        lastLength = target.getText().length();
        formatter = PhoneNumberUtil.getInstance().getAsYouTypeFormatter(Locale.getDefault().getCountry());
    }

    @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 (isFormattingStopped) {
            return;
        }

        if (count > 0 && hasSeparator(s, start, count)) {
            stopFormatting();
        }
    }

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

        boolean isSymbolsChecked = loginFilter.check(s.toString());
        boolean isEmail = StringUtils.isEmailValid(s.toString());
        boolean isPhoneNumber = isPhoneNumber(s.toString());



        if (lastLength <= s.length()) {
            if (isPhoneNumber && !isFormattingStopped) {
                String formatted = reformat(s, Selection.getSelectionEnd(s));
                if (formatted != null) {
                    target.setText(formatted);
                    target.setSelection(target.getText().length());
                }

            } else if (wasPhoneNumber) {
                String unformatted = unFormatPhoneNumber(s.toString());

                target.setText(unformatted); // or s.clear(); s.append(); 
                target.setSelection(target.getText().length());
            }
        }

        lastLength = s.length();
        wasPhoneNumber = isPhoneNumber;

        if (isFormattingStopped) {
            isFormattingStopped = s.length() != 0;
        }

        target.addTextChangedListener(this);
    }

    private String unFormatPhoneNumber(String s) {

        char[] chars = s.toCharArray();

        if (s.isEmpty()) {
            return s;
        }

        if (chars[0] == '+') {
            boolean isPhoneNumber = true;
            for (int i = 1; i < chars.length; ++i) {
                if (!Character.isDigit(chars[i])) {
                    isPhoneNumber = false;
                    break;
                }
            }
            if (isPhoneNumber) {
                return s;
            }
        }

        return s.replaceAll("[\\+\\(\\)\\s\\-]+", "");
    }

    private String reformat(CharSequence s, int cursor) {
        int curIndex = cursor - 1;
        String formatted = null;
        formatter.clear();
        char lastNonSeparator = 0;
        boolean hasCursor = false;
        int len = s.length();
        for (int i = 0; i < len; i++) {
            char c = s.charAt(i);
            if (PhoneNumberUtils.isNonSeparator(c)) {
                if (lastNonSeparator != 0) {
                    formatted = getFormattedNumber(lastNonSeparator, hasCursor);
                    hasCursor = false;
                }
                lastNonSeparator = c;
            }
            if (i == curIndex) {
                hasCursor = true;
            }
        }
        if (lastNonSeparator != 0) {
            formatted = getFormattedNumber(lastNonSeparator, hasCursor);
        }
        return formatted;
    }

    private String getFormattedNumber(char lastNonSeparator, boolean hasCursor) {
        return hasCursor ? formatter.inputDigitAndRememberPosition(lastNonSeparator)
                         : formatter.inputDigit(lastNonSeparator);
    }

    private boolean isPhoneNumber(String s) {
        return !TextUtils.isEmpty(s) && Patterns.PHONE.matcher(s).matches();
    }

    private boolean hasSeparator(final CharSequence s, final int start, final int count) {
        for (int i = start; i < start + count; i++) {
            char c = s.charAt(i);
            if (!PhoneNumberUtils.isNonSeparator(c)) {
                return true;
            }
        }
        return false;
    }

    private void stopFormatting() {
        isFormattingStopped = true;
        formatter.clear();
    }

}

共1个答案

匿名用户

尝试使用Editable提供的方法

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

        boolean isSymbolsChecked = loginFilter.check(s.toString());
        boolean isEmail = StringUtils.isEmailValid(s.toString());
        boolean isPhoneNumber = isPhoneNumber(s.toString());

        if (lastLength <= s.length()) {
            if (isPhoneNumber && !isFormattingStopped) {
                String formatted = reformat(s, Selection.getSelectionEnd(s));
                if (formatted != null) {
                    s.replace(0, s.length(), formatted)
                    target.setSelection(formatted.length());
                }

            } else if (wasPhoneNumber) {
                String unformatted = unFormatPhoneNumber(s.toString());

                s.replace(0, s.length(), formatted)
                target.setSelection(formatted.length());
            }
        }

        lastLength = s.length();
        wasPhoneNumber = isPhoneNumber;

        if (isFormattingStopped) {
            isFormattingStopped = s.length() != 0;
        }

        target.addTextChangedListener(this);
    }