¿Cuál es la mejor manera de limitar la longitud del texto de EditText en Android

702

¿Cuál es la mejor manera de limitar la longitud del texto de un EditTexten Android?

¿Hay alguna manera de hacer esto a través de xml?

hpique
fuente
1
Quería establecer el número máximo de caracteres para mi EditText. Al principio no era obvio que el límite de longitud del texto fuera lo mismo. (Solo una nota para otro viajero confuso).
Katedral Pillon
La respuesta correcta está aquí : stackoverflow.com/a/19222238/276949 . Esta respuesta limita la longitud Y evita que un búfer se llene continuamente después de alcanzar el límite, lo que permite que la tecla de retroceso funcione correctamente.
Martin Konecny

Respuestas:

1381

Documentación

Ejemplo

android:maxLength="10"
Austin Hanson
fuente
26
D'oh! Lo mismo me pasó a mí. Estaba mirando el código, y no hay un método setMaxLength.
hpique
1
¿Qué hace el Cheque aquí? Solo se vincula a esta página.
¿Qué es el sueño
55
@ Vincy, eres incorrecto. La maxLengthpropiedad aún funciona.
ashishduh
66
Tenga en cuenta que android:maxLengthes equivalente a InputFilter.LengthFilter, por lo tanto, al cambiar programáticamente su filtro, también ha modificado su filtro XML.
Mr5
20
Para las personas que dicen que no funciona, tenga en cuenta que las llamadas setFiltersdejarán de android:maxLengthfuncionar, ya que sobrescribe el filtro establecido por el XML. En otras palabras, si configura algún filtro mediante programación, debe configurarlos todos mediante programación.
Ian Newson
339

use un filtro de entrada para limitar la longitud máxima de una vista de texto.

TextView editEntryView = new TextView(...);
InputFilter[] filterArray = new InputFilter[1];
filterArray[0] = new InputFilter.LengthFilter(8);
editEntryView.setFilters(filterArray);
alemán
fuente
55
Esto es muy útil si alguien ya hizo algo InputFilter. Se anula android:maxlengthen el archivo xml, por lo que debemos agregarlo de LengthFilteresta manera.
Seblis
Creo que su respuesta es la mejor respuesta, ya que es más dinámica, +1
Muhannad A.Alhariri
197
EditText editText = new EditText(this);
int maxLength = 3;    
editText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(maxLength)});
Emran Hamza
fuente
Esto es similar a la forma en que Android lo hace con el xml.
Nicolas Tyler
44
¿Como puedo establecer la longitud mínima?
Akhila Madari
@AkhilaMadari, probablemente con TextWatcher.
CoolMind
65

Una nota para las personas que ya están utilizando un filtro de entrada personalizado y que también desean limitar la longitud máxima:

Cuando asigna filtros de entrada en el código, todos los filtros de entrada establecidos previamente se borran, incluido un conjunto con android:maxLength. Descubrí esto al intentar usar un filtro de entrada personalizado para evitar el uso de algunos caracteres que no permitimos en un campo de contraseña. Después de configurar ese filtro con setFilters, ya no se observó maxLength. La solución fue establecer maxLength y mi filtro personalizado juntos mediante programación. Algo como esto:

myEditText.setFilters(new InputFilter[] {
        new PasswordCharFilter(), new InputFilter.LengthFilter(20)
});
goto10
fuente
55
Puede recuperar los filtros existentes primero como InputFilter [] existentesFiltros = editText.getFilters (); Luego agregue su filtro junto con estos filtros existentes
subair_a
39
TextView tv = new TextView(this);
tv.setFilters(new InputFilter[]{ new InputFilter.LengthFilter(250) });
ramo2712
fuente
77
Claro, solo para Android
VAdaihiep
27

He tenido este problema y considero que nos falta una forma bien explicada de hacerlo mediante programación sin perder los filtros ya establecidos.

Establecer la longitud en XML:

Como la respuesta aceptada dice correctamente, si desea definir una longitud fija para un EditText que no cambiará más en el futuro, simplemente defina en su XML EditText:

android:maxLength="10" 

Establecer la longitud mediante programación

Para establecer la longitud mediante programación, deberá establecerla a través de un InputFilter. Pero si crea un nuevo InputFilter y lo establece en el EditTextperderá todos los otros filtros ya definidos (por ejemplo, maxLines, inputType, etc.) que podría haber agregado a través de XML o programáticamente.

Entonces esto es INCORRECTO :

editText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(maxLength)});

Para evitar perder los filtros agregados previamente, necesita obtener esos filtros, agregar uno nuevo (maxLength en este caso) y volver a configurar los filtros de la EditTextsiguiente manera:

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);

Sin embargo, Kotlin lo hizo más fácil para todos, también debe agregar el filtro a los ya existentes, pero puede lograrlo con un simple:

editText.filters += InputFilter.LengthFilter(maxLength)
Ricardo
fuente
23

Para cualquiera que se pregunte cómo lograr esto, aquí está mi EditTextclase extendida EditTextNumeric.

.setMaxLength(int) - establece el número máximo de dígitos

.setMaxValue(int) - limitar el valor entero máximo

.setMin(int) - limitar el valor entero mínimo

.getValue() - obtener valor entero

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;
        }
    }
}

Ejemplo de uso:

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

Todos los demás métodos y atributos que se aplican a EditText, por supuesto, también funcionan.

Martynas Januškauskas
fuente
1
Sería mejor si agregamos esto en xml Layout. Recibo un error con esto cuando uso xml Causado por: android.view.InflateException: línea de archivo XML binario # 47: Error al inflar la clase com.passenger.ucabs.utils.EditTextNumeric
Shihab Uddin
@Martynas ¿Tienes el mismo error que Shihab_returns alguna solución?
Pranaysharma
17

Debido a la observación de goto10, armé el siguiente código para protegerlo contra la pérdida de otros filtros al configurar la longitud máxima:

/**
 * 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
fuente
3
Es posible que desee actualizar el código ligeramente. La matriz asignada debe ser curFilters.length + 1 en tamaño y después de crear newFilters, no configuró "this" en la matriz recién asignada. InputFilter newFilters [] = new 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
fuente
12

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);

Kotlin:

editText.filters += InputFilter.LengthFilter(maxLength)
João Carlos
fuente
8

Otra forma de lograr esto es agregando la siguiente definición al archivo 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"/>

Esto limitará la longitud máxima del EditTextwidget a 6 caracteres.

usuario2586194
fuente
6

Desde material.io , puede usar TextInputEditTextcombinado con 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>

Puede configurar una contraseña EditText con dibujable:

ejemplo de contraseña

O puede limitar la longitud del texto con / sin contador:

ejemplo contrario

Dependencia:

implementation 'com.google.android.material:material:1.1.0-alpha02'
RonTLV
fuente
6

XML

android:maxLength="10"

Programáticamente:

int maxLength = 10;
InputFilter[] filters = new InputFilter[1];
filters[0] = new InputFilter.LengthFilter(maxLength);
yourEditText.setFilters(filters);

Nota: internamente, EditText y TextView analizan el valor de android:maxLengthen XML y lo utilizan InputFilter.LengthFilter()para aplicarlo.

Ver: TextView.java # L1564

nhoxbypass
fuente
2

Esta es una clase EditText personalizada que permite que el filtro de longitud viva junto con otros filtros. Gracias a la respuesta de Tim Gallagher (abajo)

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
fuente
2

de manera simple en xml:

android:maxLength="4"

si necesita establecer 4 caracteres en xml edit-text, use esto

<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
fuente
2

Esto funciona bien ...

android:maxLength="10"

esto aceptará solo 10caracteres.

Sanjay Kumaar
fuente
2

Pruebe esto para Java mediante programación :

myEditText(new InputFilter[] {new InputFilter.LengthFilter(CUSTOM_MAX_LEN)});
reza_khalafi
fuente
1
Olvidó llamar al método, por lo que debería verse así:myEditText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(CUSTOM_MAX_LEN)});
StevenTB
1

Había visto muchas buenas soluciones, pero me gustaría dar una solución que considero más completa y fácil de usar, que incluye:

1, longitud límite.
2, si ingresa más, devuelva la llamada para activar su brindis.
3, el cursor puede estar en el medio o la cola.
4, el usuario puede ingresar pegando una cadena.
5, siempre descarte la entrada de desbordamiento y mantenga el origen.

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();
        }
    }
}));

Lo que no pude hacer es que, si el usuario resalta una parte de la entrada actual e intenta pegar una cadena muy larga, no sé cómo restaurar el resaltado.

Por ejemplo, la longitud máxima se establece en 10, el usuario ingresa '12345678' y marca '345' como resaltado, e intenta pegar una cadena de '0000' que excederá la limitación.

Cuando intento usar edit_text.setSelection (start = 2, end = 4) para restaurar el estado del origen, el resultado es que simplemente inserta 2 espacios como '12 345 678 ', no el resaltado de origen. Me gustaría que alguien lo resuelva.

hyyou2010
fuente
1

Puede usar android:maxLength="10"en EditText. (Aquí el límite es de hasta 10 caracteres)

Jocelin
fuente
0

Kotlin:

edit_text.filters += InputFilter.LengthFilter(10)

ZTE Blade A520Tiene un efecto extraño. Cuando escribe más de 10 símbolos (por ejemplo, 15), EditTextmuestra los primeros 10, pero otros 5 no son visibles ni accesibles. Pero cuando elimina símbolos con Backspace, primero elimina los 5 símbolos correctos y luego elimina los 10 restantes. Para superar este comportamiento, use una solución :

android:inputType="textNoSuggestions|textVisiblePassword"
android:maxLength="10"

o esto:

android:inputType="textNoSuggestions"

o esto, si quieres tener sugerencias:

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
fuente
0

de manera simple en xml:

android:maxLength="@{length}"

para configurarlo mediante programación puede usar la siguiente función

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
fuente