Android EditText maxLength позволяет пользователю вводить больше

Я уже установил атрибут maxLength для виджета EditText в файле макета xml и ограничивает отображение символов.

Но он по-прежнему позволяет пользователю нажимать больше букв на клавиатуре, а обратная ссылка удаляет эти дополнительные нажатия, а не последнюю букву на дисплее.

Я считаю, что это не так, как должно быть. Нажатие клавиш после достижения предела должно прекратить принимать больше ввода, даже если оно не отображается.

Любое исправление на этом?

Обновление

На основе приведенного ниже ответа для многострочного EditText добавьте также атрибут textMultiLine.

android:inputType="textFilter|textMultiLine"

Ответ 1

  • Отключить автоматические предложения (android:inputType="textFilter" или textNoSuggestions):
  • Установить maxLength

    <EditText
       android:id="@+id/editText"
       android:inputType="textFilter"
       android:maxLength="8"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" />
    

Надеюсь, это поможет

Ответ 2

К сожалению, следующий ответ не работает. Тем не менее, это помогло нам выяснить, что ошибка, упомянутая Poly Bug, не воспроизводится, если ввод начинается с числа.


Вы можете использовать TextWatcher для прослушивания изменений EditText и запретить пользователю вводить слишком много символов в поле. Для меня работает следующий код:

final int maxLength = 10;
EditText editText = (EditText) findViewById(R.id.my_edittext_id);
editText.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) {}

    @Override
    public void afterTextChanged(Editable s) {
        if (s.length() >= maxLength) s.delete(maxLength, s.length());
    }
});

В afterTextChanged код сравнивает длину вставленного текста с максимальной длиной maxLength и удаляет все лишние символы.


Вы можете заменить все стандартные классы EditText следующим классом, чтобы использовать слушатель в сочетании с атрибутом maxLength XML:

public class MyMaxLengthEditText extends EditText {
    public static final String XML_NAMESPACE_ANDROID = "http://schemas.android.com/apk/res/android";
    private final int mMaxLength;

    public MyMaxLengthEditText(Context context) {
        super(context, null);
        mMaxLength = -1;
    }

    public MyMaxLengthEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        mMaxLength = attrs.getAttributeIntValue(XML_NAMESPACE_ANDROID, "maxLength", -1);
        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) {}

            @Override
            public void afterTextChanged(Editable s) {
                if (s.length() >= mMaxLength) s.delete(mMaxLength, s.length());
            }
        });
    }
}

Ответ 3

Вы можете использовать InputFilter

InputFilters могут быть привязаны к Editables для ограничения изменений которые могут быть сделаны с ними.

Xml

    <EditText
   android:id="@+id/edit_Text"
   android:layout_width="match_parent"
   android:layout_height="wrap_content" />

Класс Java

int maxLengthofYourEditText = 5;    // Set Your Limit 
edit_TextObj.setFilters(new InputFilter[] {new InputFilter.LengthFilter(maxLengthofYourEditText)});

Ответ 4

Я также столкнулся с этой ситуацией, когда имел ряд полей, содержащих 1 символ (обычный пин-код).

Мой выбор основан на ответе @jmeinke.

Создайте макет, содержащий несколько EditText с android:maxLength="2" (мы введем 1 символ в любой из них и перейдем к другому EditText. Странно, но на некоторых телефонах приведенный ниже код работает даже для maxLength = 1).

class YourTextWatcher(
    private val prevEdit: EditText?,
    private val currEdit: EditText,
    private val nextEdit: EditText?,
    private val method: () -> Unit
) : TextWatcher {
    override fun afterTextChanged(s: Editable?) {
        if (s.isNullOrEmpty()) {
            prevEdit?.requestFocus()
        } else {
            if (s.length > 1) {
                if (currEdit.selectionEnd > 1) {
                    // If stand on second position of EditText and enter new symbol, 
                    // will move to next EditText copying second symbol.
                    val secondSymbol = s.substring(1, 2)
                    nextEdit?.setText(secondSymbol)
                }
                // Remove second symbol.
                s.delete(1, s.length)
            }
            nextEdit?.requestFocus()
            nextEdit?.setSelection(nextEdit.length(), nextEdit.length())
            method()
        }
    }

    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
    }

    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
    }
}

Затем для всех EditText сделайте следующее:

currEdit.addTextChangedListener(
    YourTextWatcher(prevEdit, currEdit, nextEdit) { yourMethodToValidateText() })

Вместо prevEdit, currEdit, nextEdit устанавливает ваши элементы управления EditText. Например, для первого:

edit1.addTextChangedListener(
    YourTextWatcher(null, edit1, edit2) { yourMethodToValidateText() })

yourMethodToValidateText() - это метод, который проверяет введенные символы. Например, вы можете проверить, заполнены ли все EditText.

Это решение имеет ошибку, когда вы пытаетесь нажать BackSpace в пустом EditText. Ничего не происходит, вы не перейдете на предыдущий EditText. Вы можете поймать BackSpace в View.OnKeyListener, но он может пересекаться с TextWatcher. Также я не проверял ситуацию, когда копировал и вставлял текст в EditText, забыл проверить, что происходит, когда выделите текст в EditText и нажмите Delete.