Jaki jest najlepszy sposób ograniczenia długości tekstu EditText w Androidzie

700

Jaki jest najlepszy sposób ograniczenia długości tekstu EditTextw Androidzie?

Czy jest na to sposób za pomocą xml?

hpique
źródło
1
Chciałem ustawić maksymalną liczbę znaków dla mojego EditText. Na początku nie było oczywiste, że limit długości tekstu był taki sam. (Tylko uwaga dla innego zdezorientowanego podróżnika).
Katedral Pillon
Poprawna odpowiedź jest tutaj : stackoverflow.com/a/19222238/276949 . Ta odpowiedź ogranicza długość ORAZ zapobiega ciągłemu zapełnianiu się bufora po osiągnięciu limitu, dzięki czemu klawisz Backspace działa poprawnie.
Martin Konecny,

Odpowiedzi:

1378

Dokumentacja

Przykład

android:maxLength="10"
Austin Hanson
źródło
26
Nie! To samo przytrafiło mi się. Patrzyłem na kod i nie ma metody setMaxLength.
hpique
1
co robi tutaj Check? To tylko linki do tej strony.
czym jest sen
5
@Vincy, jesteś w błędzie. maxLengthNieruchomość nadal działa.
ashishduh
6
Pamiętaj, że android:maxLengthjest to równoważne z tym InputFilter.LengthFilter, więc programowo zmieniając filtr, zmodyfikowałeś również jego filtr XML.
mr5
20
Ludziom, którzy twierdzą, że to nie działa, pamiętaj, że wywołanie setFiltersprzestanie android:maxLengthdziałać, ponieważ zastąpi zestaw filtrów ustawiony przez XML. Innymi słowy, jeśli ustawisz dowolne filtry programowo, musisz ustawić je wszystkie programowo.
Ian Newson
339

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);
nocnik
źródło
5
Jest to bardzo przydatne, jeśli ktoś już coś zrobił InputFilter. Zastępuje android:maxlengthw pliku xml, więc musimy dodać w LengthFilterten sposób.
Seblis,
Myślę, że twoja odpowiedź jest najlepsza, ponieważ jest bardziej dynamiczna, +1
Muhannad A.Alhariri
197
EditText editText = new EditText(this);
int maxLength = 3;    
editText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(maxLength)});
Emran Hamza
źródło
Jest to podobne do sposobu, w jaki android robi to za pomocą xml.
Nicolas Tyler,
4
Jak ustawić minimalną długość?
Akhila Madari
@AkhilaMadari, prawdopodobnie z TextWatcher.
CoolMind,
65

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)
});
goto10
źródło
5
Możesz najpierw pobrać istniejące filtry, ponieważ InputFilter [] existFilters = editText.getFilters (); Następnie dodaj swój filtr wraz z istniejącymi filtrami
subair_a
39
TextView tv = new TextView(this);
tv.setFilters(new InputFilter[]{ new InputFilter.LengthFilter(250) });
ramo2712
źródło
7
Jasne, tylko dla Androida
VAdaihiep
27

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 EditTextnastę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)
Ricardo
źródło
23

Dla każdego, kto zastanawia się, jak to osiągnąć, oto moja rozszerzona EditTextklasa 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);

EditTextOczywiście wszystkie inne metody i atrybuty, które mają zastosowanie , również działają.

Martynas Januškauskas
źródło
1
Byłoby lepiej, gdybyśmy dodali to w układzie xml. Dostaję błąd podczas używania xml Przyczyna: android.view.InflateException: Binarny plik XML linii # 47: Błąd podczas pompowania klasy com.passenger.ucabs.utils.EditTextNumeric
Shihab Uddin
@Martynas Masz taki sam błąd jak Shihab_returns jakieś rozwiązanie?
Pranaysharma
17

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 });
    }
}
Tim Gallagher
źródło
3
Możesz nieco zaktualizować kod. Przydzielona tablica musi mieć rozmiar curFilters.length + 1, a po utworzeniu nowych filtrów nie ustawiono „to” na nowo przydzieloną tablicę. InputFilter newFilters [] = nowy InputFilter [curFilters.length + 1]; System.arraycopy (curFilters, 0, newFilters, 0, curFilters.length); this.setFilters (newFilters);
JavaCoderEx
15
//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()});
Kishore Reddy
źródło
12

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)
João Carlos
źródło
8

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ść EditTextwidgetu do 6 znaków.

użytkownik2586194
źródło
6

Z material.io możesz używać w TextInputEditTextpołą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:

przykład hasła

Lub możesz ograniczyć długość tekstu za pomocą / bez licznika:

licznik przykład

Zależność:

implementation 'com.google.android.material:material:1.1.0-alpha02'
RonTLV
źródło
6

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:maxLengthw XML i używają InputFilter.LengthFilter()do jej zastosowania.

Zobacz: TextView.java # L1564

nhoxbypass
źródło
2

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 });
        }
    }
}
Gal Rom
źródło
2

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" />
Navadip Patel
źródło
2

To działa dobrze ...

android:maxLength="10"

to zaakceptuje tylko 10postacie.

Sanjay Kumaar
źródło
2

Wypróbuj programowo dla Java :

myEditText(new InputFilter[] {new InputFilter.LengthFilter(CUSTOM_MAX_LEN)});
reza_khalafi
źródło
1
Zapomniałeś wywołać metodę, więc powinna wyglądać następująco:myEditText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(CUSTOM_MAX_LEN)});
StevenTB
1

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ł.

hyyou2010
źródło
1

Możesz użyć android:maxLength="10"w EditText. (Tutaj limit wynosi do 10 znaków)

Jocelin
źródło
0

Kotlin:

edit_text.filters += InputFilter.LengthFilter(10)

ZTE Blade A520ma dziwny efekt. Gdy wpiszesz więcej niż 10 symboli (na przykład 15), EditTextpokazuje 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)
CoolMind
źródło
0

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()]));
    }
}
Mohamed Fadel Buffon
źródło