Какой лучший способ ограничить длину текста EditTextв Android?
Есть ли способ сделать это через XML?
Какой лучший способ ограничить длину текста EditTextв Android?
Есть ли способ сделать это через XML?
Ответы:
maxLengthНедвижимость по- прежнему работает.
android:maxLengthэто эквивалентно InputFilter.LengthFilter, поэтому при программном изменении его фильтра вы также изменили его XML-фильтр.
setFiltersперестанут android:maxLengthработать, потому что это перезаписывает фильтр, установленный XML. Другими словами, если вы устанавливаете какие-либо фильтры программно, вы должны установить их все программно.
используйте входной фильтр, чтобы ограничить максимальную длину текстового представления.
TextView editEntryView = new TextView(...);
InputFilter[] filterArray = new InputFilter[1];
filterArray[0] = new InputFilter.LengthFilter(8);
editEntryView.setFilters(filterArray);
InputFilter. Он переопределяет android:maxlengthв файле XML, поэтому нам нужно добавить LengthFilterэтот путь.
EditText editText = new EditText(this);
int maxLength = 3;
editText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(maxLength)});
TextWatcher.
Примечание для людей, которые уже используют пользовательский фильтр ввода и также хотят ограничить максимальную длину:
Когда вы назначаете входные фильтры в коде, все ранее установленные входные фильтры очищаются, включая один, установленный с помощью android:maxLength. Я узнал об этом, когда пытался использовать пользовательский фильтр ввода, чтобы предотвратить использование некоторых символов, которые мы не разрешаем в поле пароля. После установки этого фильтра с помощью setFilters maxLength больше не наблюдалось. Решением было установить maxLength и мой пользовательский фильтр вместе программно. Что-то вроде этого:
myEditText.setFilters(new InputFilter[] {
new PasswordCharFilter(), new InputFilter.LengthFilter(20)
});
У меня была эта проблема, и я считаю, что мы упускаем хорошо объясненный способ сделать это программно, не теряя уже установленные фильтры.
Установка длины в XML:
Как правильно говорится в принятом ответе, если вы хотите задать для EditText фиксированную длину, которую вы не будете менять в будущем, просто определите в XML-файле EditText:
android:maxLength="10"
Установка длины программно
Чтобы установить длину программно, вам нужно установить ее через InputFilter. Но если вы создадите новый InputFilter и установите его вEditText вы потеряете все другие уже определенные фильтры (например, maxLines, inputType и т. Д.), Которые вы могли бы добавить либо через XML, либо программно.
Так что это НЕПРАВИЛЬНО :
editText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(maxLength)});
Чтобы не потерять ранее добавленные фильтры, вам нужно получить эти фильтры, добавить новый (в данном случае 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(maxLength);
editText.setFilters(newFilters);
Однако Kotlin упростил задачу для всех, вам также нужно добавить фильтр к уже существующим, но это можно сделать с помощью простого:
editText.filters += InputFilter.LengthFilter(maxLength)
Для всех, кто интересуется, как этого добиться, вот мой расширенный 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
android:maxLength="10"
Ява:
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)
Другой способ добиться этого - добавить следующее определение в файл 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 символов.
Из material.io вы можете использовать в TextInputEditTextсочетании с TextInputLayout:
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:counterEnabled="true"
app:counterMaxLength="1000"
app:passwordToggleEnabled="false">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edit_text"
android:hint="@string/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLength="1000"
android:gravity="top|start"
android:inputType="textMultiLine|textNoSuggestions"/>
</com.google.android.material.textfield.TextInputLayout>
Вы можете настроить пароль EditText с помощью drawable:
Или вы можете ограничить длину текста с / без счетчика:
Зависимость:
implementation 'com.google.android.material:material:1.1.0-alpha02'
XML
android:maxLength="10"
Программный:
int maxLength = 10;
InputFilter[] filters = new InputFilter[1];
filters[0] = new InputFilter.LengthFilter(maxLength);
yourEditText.setFilters(filters);
Примечание: внутренне, EditText & TextView анализируют значение android:maxLengthв XML и используют InputFilter.LengthFilter()для его применения.
Смотрите: TextView.java # L1564
Это пользовательский класс 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, используйте
<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символы.
Попробуйте это для Java программно :
myEditText(new InputFilter[] {new InputFilter.LengthFilter(CUSTOM_MAX_LEN)});
myEditText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(CUSTOM_MAX_LEN)});
Я видел много хороших решений, но я хотел бы дать, как мне кажется, более полное и удобное решение, которое включает в себя:
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', а не выделение источника. Я бы хотел, чтобы кто-то решил это.
Котлин:
edit_text.filters += InputFilter.LengthFilter(10)
ZTE Blade A520имеет странный эффект. Когда вы набираете более 10 символов (например, 15), EditTextотображаются первые 10, но остальные 5 не видны и недоступны. Но когда вы удаляете символы с помощью Backspace, сначала удаляются правильные 5 символов, а затем удаляются оставшиеся 10. Чтобы преодолеть это поведение, используйте решение :
android:inputType="textNoSuggestions|textVisiblePassword"
android:maxLength="10"
или это:
android:inputType="textNoSuggestions"
или это, если вы хотите получить предложения:
private class EditTextWatcher(private val view: EditText) : TextWatcher {
private var position = 0
private var oldText = ""
override fun afterTextChanged(s: Editable?) = Unit
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
oldText = s?.toString() ?: ""
position = view.selectionStart
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
val newText = s?.toString() ?: ""
if (newText.length > 10) {
with(view) {
setText(oldText)
position = if (start > 0 && count > 2) {
// Text paste in nonempty field.
start
} else {
if (position in 1..10 + 1) {
// Symbol paste in the beginning or middle of the field.
position - 1
} else {
if (start > 0) {
// Adding symbol to the end of the field.
start - 1
} else {
// Text paste in the empty field.
0
}
}
}
setSelection(position)
}
}
}
}
// Usage:
editTextWatcher = EditTextWatcher(view.edit_text)
view.edit_text.addTextChangedListener(editTextWatcher)
это простой способ в xml:
android:maxLength="@{length}"
для его настройки вы можете использовать следующую функцию
public static void setMaxLengthOfEditText(EditText editText, int length) {
InputFilter[] filters = editText.getFilters();
List arrayList = new ArrayList();
int i2 = 0;
if (filters != null && filters.length > 0) {
int length = filters.length;
int i3 = 0;
while (i2 < length) {
Object obj = filters[i2];
if (obj instanceof LengthFilter) {
arrayList.add(new LengthFilter(length));
i3 = 1;
} else {
arrayList.add(obj);
}
i2++;
}
i2 = i3;
}
if (i2 == 0) {
arrayList.add(new LengthFilter(length));
}
if (!arrayList.isEmpty()) {
editText.setFilters((InputFilter[]) arrayList.toArray(new InputFilter[arrayList.size()]));
}
}