Ограничить длину текста EditText в Android


каков наилучший способ ограничить длину текста EditText в Android?

есть ли способ сделать это с помощью xml?

16 562

16 ответов:

документация

пример

android:maxLength="10"

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

TextView editEntryView = new TextView(...);
InputFilter[] filterArray = new InputFilter[1];
filterArray[0] = new InputFilter.LengthFilter(8);
editEntryView.setFilters(filterArray);
EditText editText = new EditText(this);
int maxLength = 3;    
editText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(maxLength)});

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

при назначении входных фильтров в код все ранее установленные входные фильтры очищаются, в том числе один набор с android:maxLength. Я обнаружил это при попытке использовать пользовательский входной фильтр, чтобы предотвратить использование некоторых символов, которые мы не разрешаем в поле пароля. После установки этого фильтра с помощью setFilters максимальная длина больше не наблюдалась. Решение было чтобы установить maxlength и мой пользовательский фильтр программно. Что-то вроде этого:

myEditText.setFilters(new InputFilter[] {
        new PasswordCharFilter(), new InputFilter.LengthFilter(20)
});
TextView tv = new TextView(this);
tv.setFilters(new InputFilter[]{ new InputFilter.LengthFilter(250) });

для тех, кто еще задается вопросом, как этого достичь, вот мой расширенный EditText класс EditTextNumeric.

.setMaxLength(int) - устанавливает максимальное количество цифр

.setMaxValue(int) - ограничить максимальное целочисленное значение

.setMin(int) - предельное минимальное целочисленное значение

.getValue() - получить целочисленное значение

import android.content.Context;
import android.text.InputFilter;
import android.text.InputType;
import android.widget.EditText;

public class EditTextNumeric extends EditText {
    protected int max_value = Integer.MAX_VALUE;
    protected int min_value = Integer.MIN_VALUE;

    // constructor
    public EditTextNumeric(Context context) {
        super(context);
        this.setInputType(InputType.TYPE_CLASS_NUMBER);
    }

    // checks whether the limits are set and corrects them if not within limits
    @Override
    protected void onTextChanged(CharSequence text, int start, int before, int after) {
        if (max_value != Integer.MAX_VALUE) {
            try {
                if (Integer.parseInt(this.getText().toString()) > max_value) {
                    // change value and keep cursor position
                    int selection = this.getSelectionStart();
                    this.setText(String.valueOf(max_value));
                    if (selection >= this.getText().toString().length()) {
                        selection = this.getText().toString().length();
                    }
                    this.setSelection(selection);
                }
            } catch (NumberFormatException exception) {
                super.onTextChanged(text, start, before, after);
            }
        }
        if (min_value != Integer.MIN_VALUE) {
            try {
                if (Integer.parseInt(this.getText().toString()) < min_value) {
                    // change value and keep cursor position
                    int selection = this.getSelectionStart();
                    this.setText(String.valueOf(min_value));
                    if (selection >= this.getText().toString().length()) {
                        selection = this.getText().toString().length();
                    }
                    this.setSelection(selection);
                }
            } catch (NumberFormatException exception) {
                super.onTextChanged(text, start, before, after);
            }
        }
        super.onTextChanged(text, start, before, after);
    }

    // set the max number of digits the user can enter
    public void setMaxLength(int length) {
        InputFilter[] FilterArray = new InputFilter[1];
        FilterArray[0] = new InputFilter.LengthFilter(length);
        this.setFilters(FilterArray);
    }

    // set the maximum integer value the user can enter.
    // if exeeded, input value will become equal to the set limit
    public void setMaxValue(int value) {
        max_value = value;
    }
    // set the minimum integer value the user can enter.
    // if entered value is inferior, input value will become equal to the set limit
    public void setMinValue(int value) {
        min_value = value;
    }

    // returns integer value or 0 if errorous value
    public int getValue() {
        try {
            return Integer.parseInt(this.getText().toString());
        } catch (NumberFormatException exception) {
            return 0;
        }
    }
}

пример использования:

final EditTextNumeric input = new EditTextNumeric(this);
input.setMaxLength(5);
input.setMaxValue(total_pages);
input.setMinValue(1);

все другие методы и атрибуты, которые применяются к EditText, конечно, тоже работают.

из-за наблюдения goto10, я собрал следующий код для защиты от потери других фильтров с установкой максимальной длины:

/**
 * This sets the maximum length in characters of an EditText view. Since the
 * max length must be done with a filter, this method gets the current
 * filters. If there is already a length filter in the view, it will replace
 * it, otherwise, it will add the max length filter preserving the other
 * 
 * @param view
 * @param length
 */
public static void setMaxLength(EditText view, int length) {
    InputFilter curFilters[];
    InputFilter.LengthFilter lengthFilter;
    int idx;

    lengthFilter = new InputFilter.LengthFilter(length);

    curFilters = view.getFilters();
    if (curFilters != null) {
        for (idx = 0; idx < curFilters.length; idx++) {
            if (curFilters[idx] instanceof InputFilter.LengthFilter) {
                curFilters[idx] = lengthFilter;
                return;
            }
        }

        // since the length filter was not part of the list, but
        // there are filters, then add the length filter
        InputFilter newFilters[] = new InputFilter[curFilters.length + 1];
        System.arraycopy(curFilters, 0, newFilters, 0, curFilters.length);
        newFilters[curFilters.length] = lengthFilter;
        view.setFilters(newFilters);
    } else {
        view.setFilters(new InputFilter[] { lengthFilter });
    }
}
//Set Length filter. Restricting to 10 characters only
editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(MAX_LENGTH)});

//Allowing only upper case characters
editText.setFilters(new InputFilter[]{new InputFilter.AllCaps()});

//Attaching multiple filters
editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(MAX_LENGTH), new InputFilter.AllCaps()});

еще один способ добиться этого-добавить в XML-файл следующее определение:

<EditText
    android:id="@+id/input"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:inputType="number"
    android:maxLength="6"
    android:hint="@string/hint_gov"
    android:layout_weight="1"/>

это ограничит максимальную длину EditText виджет до 6 символов.

у меня была эта проблема, и я считаю, что нам не хватает хорошо объясненного способа сделать это программно, не теряя уже установленные фильтры.

установка длины в XML:

как правильно указано в принятом ответе, если вы хотите определить фиксированную длину для EditText, которую вы не будете изменять в будущем, просто определите в своем EditText XML:

android:maxLength="10" 

настройка длины программно

вот проблема, чтобы установить длину программно вам нужно будет установить InputFilter но как только вы установите его, все остальные фильтры уйдут (например, maxLines, inputType и т. д.). Чтобы избежать потери предыдущих фильтров, вам нужно получить эти предыдущие примененные фильтры, добавить maxLength и установить фильтры обратно в EditText следующим образом:

InputFilter[] editFilters = editText.getFilters();
InputFilter[] newFilters = new InputFilter[editFilters.length + 1];
System.arraycopy(editFilters, 0, newFilters, 0, editFilters.length);
newFilters[editFilters.length] = new InputFilter.LengthFilter(10); //the desired length
editText.setFilters(newFilters);

Xml

android:maxLength="10"

Java:

InputFilter[] editFilters = editText.getFilters();
InputFilter[] newFilters = new InputFilter[editFilters.length + 1];
System.arraycopy(editFilters, 0, newFilters, 0, editFilters.length);
newFilters[editFilters.length] = new InputFilter.LengthFilter(maxLength);
editText.setFilters(newFilters);

Котлин:

editText.filters += InputFilter.LengthFilter(maxLength)

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

import android.content.Context;
import android.text.InputFilter;
import android.util.AttributeSet;
import android.widget.EditText;


public class EditTextMultiFiltering extends EditText{

    public EditTextMultiFiltering(Context context) {
        super(context);
    }

    public EditTextMultiFiltering(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public EditTextMultiFiltering(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public void setMaxLength(int length) {
        InputFilter curFilters[];
        InputFilter.LengthFilter lengthFilter;
        int idx;

        lengthFilter = new InputFilter.LengthFilter(length);

        curFilters = this.getFilters();
        if (curFilters != null) {
            for (idx = 0; idx < curFilters.length; idx++) {
                if (curFilters[idx] instanceof InputFilter.LengthFilter) {
                    curFilters[idx] = lengthFilter;
                    return;
                }
            }

            // since the length filter was not part of the list, but
            // there are filters, then add the length filter
            InputFilter newFilters[] = new InputFilter[curFilters.length + 1];
            System.arraycopy(curFilters, 0, newFilters, 0, curFilters.length);
            newFilters[curFilters.length] = lengthFilter;
            this.setFilters(newFilters);
        } else {
            this.setFilters(new InputFilter[] { lengthFilter });
        }
    }
}

это простой способ в XML:

android:maxLength="4"

Если вам требуется установить 4 символа в XML edit-text so, используйте это

<EditText
    android:id="@+id/edtUserCode"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:maxLength="4"
    android:hint="Enter user code" />

это прекрасно работает...

android:maxLength="10"

это будет принимать только 10 символы.

Я видел много хороших решений, но я хотел бы сказать, что я думаю как более полное и удобное решение, которое включает:

1, предельная длина.
2, Если ввод больше, дать обратный вызов, чтобы вызвать ваш тост.
3, курсор может быть на середине или хвосте.
4, пользователь может ввести путем вставки строки.
5, Всегда сбрасывают входной сигнал переполнения и держат начало.

public class LimitTextWatcher implements TextWatcher {

    public interface IF_callback{
        void callback(int left);
    }

    public IF_callback if_callback;

    EditText editText;
    int maxLength;

    int cursorPositionLast;
    String textLast;
    boolean bypass;

    public LimitTextWatcher(EditText editText, int maxLength, IF_callback if_callback) {

        this.editText = editText;
        this.maxLength = maxLength;
        this.if_callback = if_callback;
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        if (bypass) {

            bypass = false;

        } else {

            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(s);
            textLast = stringBuilder.toString();

            this.cursorPositionLast = editText.getSelectionStart();
        }
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

    }

    @Override
    public void afterTextChanged(Editable s) {
        if (s.toString().length() > maxLength) {

            int left = maxLength - s.toString().length();

            bypass = true;
            s.clear();

            bypass = true;
            s.append(textLast);

            editText.setSelection(this.cursorPositionLast);

            if (if_callback != null) {
                if_callback.callback(left);
            }
        }

    }

}


edit_text.addTextChangedListener(new LimitTextWatcher(edit_text, MAX_LENGTH, new LimitTextWatcher.IF_callback() {
    @Override
    public void callback(int left) {
        if(left <= 0) {
            Toast.makeText(MainActivity.this, "input is full", Toast.LENGTH_SHORT).show();
        }
    }
}));

что мне не удалось сделать, если пользователь выделит часть текущего ввода и попытается вставить очень длинную строку, я не знаю как восстановить выделить.

например, максимальная длина установлена в 10, пользователь ввел '12345678 'и пометил' 345 'как выделение и попытался вставить строку' 0000', которая превысит ограничение.

когда я пытаюсь использовать edit_text.setSelection (start=2, end=4) для восстановления исходного состояния, в результате, он просто вставляет 2 пробела как '12 345 678', а не выделение источника. Я бы хотел, чтобы кто-то решил это.

вы можете использовать android:maxLength="10" в edittext.(Здесь ограничение до 10 символов)