Подтвердить что ты не робот

InputFilter на EditText вызывает повторяющийся текст

Я пытаюсь реализовать EditText, который ограничивает ввод только символами Capital [A-Z0-9] с цифрами.

Я начал с метода InputFilter с некоторого сообщения. Но здесь я получаю одну проблему на Samsung Galaxy Tab 2, но не в эмуляторе или Nexus 4.

Проблема такова:

  • Когда я набираю "A", текст показывает как "A" его хороший
  • Теперь, когда я набираю "B", поэтому текст должен быть "AB", но он дает мне "AAB" это выглядит очень странно.

Короче говоря, он повторяет символы

Вот код, с которым я работаю с этим кодом:

public class DemoFilter implements InputFilter {

    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart,
            int dend) {

        if (source.equals("")) { // for backspace
            return source;
        }
        if (source.toString().matches("[a-zA-Z0-9 ]*")) // put your constraints
                                                        // here
        {
            return source.toString().toUpperCase();
        }
        return "";
    }
}

Код файла XML:

<EditText
    android:id="@+id/et_licence_plate_1"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="3"
    android:hint="0"
    android:imeOptions="actionNext"
    android:inputType="textNoSuggestions"
    android:maxLength="3"
    android:singleLine="true"
    android:textSize="18px" >
</EditText>

Я полностью застрял на этом, поэтому любая помощь здесь будет очень признательна.

4b9b3361

Ответ 1

Проблема дублирования символов происходит из-за плохой реализации InputFilter. Скорее возвратите null, если замена не должна меняться:

@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
    boolean keepOriginal = true;
    StringBuilder sb = new StringBuilder(end - start);
    for (int i = start; i < end; i++) {
        char c = source.charAt(i);
        if (isCharAllowed(c)) // put your condition here
            sb.append(c);
        else
            keepOriginal = false;
    }
    if (keepOriginal)
        return null;
    else {
        if (source instanceof Spanned) {
            SpannableString sp = new SpannableString(sb);
            TextUtils.copySpansFrom((Spanned) source, start, end, null, sp, 0);
            return sp;
        } else {
            return sb;
        }           
    }
}

private boolean isCharAllowed(char c) {
    return Character.isUpperCase(c) || Character.isDigit(c);
}

Ответ 2

Я нашел много ошибок в Android InputFilter, я не уверен, что это ошибки или они так и были. Но определенно это не соответствовало моим требованиям. Поэтому я решил использовать TextWatcher вместо InputFilter

private String newStr = "";

myEditText.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            // Do nothing
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            String str = s.toString();
            if (str.isEmpty()) {
                myEditText.append(newStr);
                newStr = "";
            } else if (!str.equals(newStr)) {
                // Replace the regex as per requirement
                newStr = str.replaceAll("[^A-Z0-9]", "");
                myEditText.setText("");
            }
        }

        @Override
        public void afterTextChanged(Editable s) {
            // Do nothing
        }
    });

Приведенный выше код не позволяет пользователям вводить специальный символ в ваш EditText. Разрешены только буквенные буквенные символы.

Ответ 3

InputFilters можно подключить к Editable S, чтобы ограничить изменения, которые могут быть сделаны для них. Обратите внимание, что он подчеркивает сделанные изменения, а не весь текст, который он содержит.

Следуйте, как указано ниже...

 public class DemoFilter implements InputFilter {

        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart,
                int dend) {

            if (source.equals("")) { // for backspace
                return source;
            }
            if (source.toString().matches("[a-zA-Z0-9 ]*")) // put your constraints
                                                            // here
            {
               char[] ch = new char[end - start];

              TextUtils.getChars(source, start, end, ch, 0);

                // make the characters uppercase
                String retChar = new String(ch).toUpperCase();
                return retChar;
            }
            return "";
        }
    }

Ответ 4

Я столкнулся с той же проблемой, после того, как исправил ее с помощью размещенных здесь решений, осталась еще проблема с клавиатурами с автозаполнением. Одним из решений является установка inputType как "visiblePassword", но сокращение функциональности не так ли?

Я смог исправить решение, возвращая ненулевой результат в методе filter(), используя вызов

TextUtils.copySpansFrom((Spanned) source, start, newString.length(), null, newString, 0);

Это копирует автоматически заполненные промежутки в новый результат и фиксирует странное поведение повторения при выборе предложений автозаполнения.

Ответ 5

попробуйте следующее:

class CustomInputFilter implements InputFilter {
    StringBuilder sb = new StringBuilder();

    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        Log.d(TAG, "filter " + source + " " + start + " " + end + " dest " + dest + " " + dstart + " " + dend);
        sb.setLength(0);
        for (int i = start; i < end; i++) {
            char c = source.charAt(i);
            if (Character.isUpperCase(c) || Character.isDigit(c) || c == ' ') {
                sb.append(c);
            } else
            if (Character.isLowerCase(c)) {
                sb.append(Character.toUpperCase(c));
            }
        }
        return sb;
    }
}

это также позволяет фильтровать, когда метод filter() принимает сразу несколько символов, например. вставляемый текст из буфера обмена

Ответ 6

Следующее решение также поддерживает возможность использования автозаполнения клавиатуры

editTextFreeNote.addTextChangedListener( new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            String newStr = s.toString();
            newStr = newStr.replaceAll( "[a-zA-Z0-9 ]*", "" );
            if(!s.toString().equals( newStr )) {
                editTextFreeNote.setText( newStr );
                editTextFreeNote.setSelection(editTextFreeNote.getText().length());
            }
        }

        @Override
        public void afterTextChanged(Editable s) {}
    } );