Jaki jest najlepszy sposób ograniczenia długości tekstu EditText
w Androidzie?
Czy jest na to sposób za pomocą xml?
Jaki jest najlepszy sposób ograniczenia długości tekstu EditText
w Androidzie?
Czy jest na to sposób za pomocą xml?
Odpowiedzi:
maxLength
Nieruchomość nadal działa.
android:maxLength
jest to równoważne z tym InputFilter.LengthFilter
, więc programowo zmieniając filtr, zmodyfikowałeś również jego filtr XML.
setFilters
przestanie android:maxLength
działać, ponieważ zastąpi zestaw filtrów ustawiony przez XML. Innymi słowy, jeśli ustawisz dowolne filtry programowo, musisz ustawić je wszystkie programowo.
użyj filtra wejściowego, aby ograniczyć maksymalną długość widoku tekstu.
TextView editEntryView = new TextView(...);
InputFilter[] filterArray = new InputFilter[1];
filterArray[0] = new InputFilter.LengthFilter(8);
editEntryView.setFilters(filterArray);
InputFilter
. Zastępuje android:maxlength
w pliku xml, więc musimy dodać w LengthFilter
ten sposób.
EditText editText = new EditText(this);
int maxLength = 3;
editText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(maxLength)});
TextWatcher
.
Uwaga dla osób, które już korzystają z niestandardowego filtra wejściowego i chcą również ograniczyć maksymalną długość:
Po przypisaniu filtrów wejściowych w kodzie wszystkie wcześniej ustawione filtry wejściowe są kasowane, w tym jeden zestaw z android:maxLength
. Przekonałem się o tym, próbując użyć niestandardowego filtra wejściowego, aby zapobiec użyciu niektórych znaków, które nie są dozwolone w polu hasła. Po ustawieniu tego filtra za pomocą setFilters nie obserwowano już maxLength. Rozwiązaniem było programowe ustawienie maxLength i mojego niestandardowego filtra. Coś takiego:
myEditText.setFilters(new InputFilter[] {
new PasswordCharFilter(), new InputFilter.LengthFilter(20)
});
Miałem ten problem i uważam, że brakuje nam dobrze wyjaśnionego sposobu robienia tego programowo bez utraty ustawionych filtrów.
Ustawianie długości w XML:
Zgodnie z prawidłową odpowiedzią, jeśli chcesz zdefiniować stałą długość w EditText, którego nie będziesz dalej zmieniać w przyszłości, po prostu zdefiniuj w EditText XML:
android:maxLength="10"
Programowe ustawianie długości
Aby programowo ustawić długość, musisz ustawić ją za pomocą InputFilter
. Ale jeśli utworzysz nowy InputFilter i ustawisz go EditText
, stracisz wszystkie inne już zdefiniowane filtry (np. MaxLines, inputType itp.), Które mogłeś dodać albo przez XML, albo programowo.
To jest NIEPRAWIDŁOWE :
editText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(maxLength)});
Aby uniknąć utraty wcześniej dodanych filtrów, musisz uzyskać te filtry, dodać nowy (w tym przypadku maxLength) i ustawić filtry z powrotem na EditText
następujące:
Jawa
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 jednak ułatwił wszystkim, musisz również dodać filtr do już istniejących, ale możesz to zrobić za pomocą prostego:
editText.filters += InputFilter.LengthFilter(maxLength)
Dla każdego, kto zastanawia się, jak to osiągnąć, oto moja rozszerzona EditText
klasa EditTextNumeric
.
.setMaxLength(int)
- ustawia maksymalną liczbę cyfr
.setMaxValue(int)
- ograniczenie maksymalnej wartości całkowitej
.setMin(int)
- ograniczenie minimalnej wartości całkowitej
.getValue()
- uzyskać wartość całkowitą
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;
}
}
}
Przykładowe użycie:
final EditTextNumeric input = new EditTextNumeric(this);
input.setMaxLength(5);
input.setMaxValue(total_pages);
input.setMinValue(1);
EditText
Oczywiście wszystkie inne metody i atrybuty, które mają zastosowanie , również działają.
Ze względu na obserwację goto10, zestawiłem następujący kod, aby zabezpieczyć się przed utratą innych filtrów z ustawieniem maksymalnej długości:
/**
* 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"
Jawa:
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)
Innym sposobem na osiągnięcie tego jest dodanie do pliku XML następującej definicji:
<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"/>
Ograniczy to maksymalną długość EditText
widgetu do 6 znaków.
Z material.io możesz używać w TextInputEditText
połączeniu z 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>
Możesz skonfigurować hasło EditText z możliwością rysowania:
Lub możesz ograniczyć długość tekstu za pomocą / bez licznika:
Zależność:
implementation 'com.google.android.material:material:1.1.0-alpha02'
XML
android:maxLength="10"
Programowo:
int maxLength = 10;
InputFilter[] filters = new InputFilter[1];
filters[0] = new InputFilter.LengthFilter(maxLength);
yourEditText.setFilters(filters);
Uwaga: wewnętrznie EditText i TextView analizują wartość android:maxLength
w XML i używają InputFilter.LengthFilter()
do jej zastosowania.
Zobacz: TextView.java # L1564
Jest to niestandardowa klasa EditText, która pozwala na stosowanie filtra Length wraz z innymi filtrami. Dzięki odpowiedzi Tima Gallaghera (poniżej)
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 });
}
}
}
prosty sposób w XML:
android:maxLength="4"
jeśli musisz ustawić 4 znaki w edytorze tekstu XML, użyj tego
<EditText
android:id="@+id/edtUserCode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLength="4"
android:hint="Enter user code" />
To działa dobrze ...
android:maxLength="10"
to zaakceptuje tylko 10
postacie.
Wypróbuj programowo dla Java :
myEditText(new InputFilter[] {new InputFilter.LengthFilter(CUSTOM_MAX_LEN)});
myEditText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(CUSTOM_MAX_LEN)});
Widziałem wiele dobrych rozwiązań, ale chciałbym podać coś, co uważam za bardziej kompletne i przyjazne dla użytkownika rozwiązanie, które obejmuje:
1, Limit długości.
2, Jeśli wprowadzisz więcej, oddzwoń, aby uruchomić toast.
3, Kursor może znajdować się na środku lub ogonie.
4, użytkownik może wprowadzić, wklejając ciąg.
5, Zawsze odrzucaj dane przelewu i zachowaj pochodzenie.
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();
}
}
}));
Nie udało mi się, jeśli użytkownik podświetli część bieżącego wejścia i spróbuje wkleić bardzo długi ciąg, nie wiem, jak przywrócić podświetlenie.
Na przykład maksymalna długość jest ustawiona na 10, użytkownik wprowadził „12345678” i oznaczył „345” jako podświetlony, i próbował wkleić ciąg „0000”, który przekroczy ograniczenia.
Kiedy próbuję użyć edit_text.setSelection (start = 2, end = 4) w celu przywrócenia stanu początkowego, wynik jest taki, że po prostu wstawiam 2 spacje jako „12 345 678”, a nie podświetlenie źródła. Chciałbym, żeby ktoś to rozwiązał.
Kotlin:
edit_text.filters += InputFilter.LengthFilter(10)
ZTE Blade A520
ma dziwny efekt. Gdy wpiszesz więcej niż 10 symboli (na przykład 15), EditText
pokazuje pierwsze 10, ale pozostałe 5 nie są widoczne i niedostępne. Ale kiedy usuwasz symbole za pomocą Backspace
, najpierw usuwa właściwe 5 symboli, a następnie usuwa pozostałe 10. Aby obejść to zachowanie, użyj rozwiązania :
android:inputType="textNoSuggestions|textVisiblePassword"
android:maxLength="10"
albo to:
android:inputType="textNoSuggestions"
lub to, jeśli chcesz mieć sugestie:
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)
prosty sposób w XML:
android:maxLength="@{length}"
do programowego ustawienia możesz użyć następującej funkcji
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()]));
}
}