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>
Я полностью застрял на этом, поэтому любая помощь здесь будет очень признательна.
Ответы
Ответ 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) {}
} );