Limitar la longitud del texto de EditText en Android

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

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

Documentación

Ejemplo

 android:maxLength="10" 

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); 
 EditText editText = new EditText(this); int maxLength = 3; editText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(maxLength)}); 

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

Cuando asigna filtros de entrada en el código, se borran todos los filtros de entrada configurados previamente, incluido un conjunto con android:maxLength . Lo descubrí cuando intentaba 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 establecer ese filtro con setFilters, maxLength ya no se observó. La solución fue establecer maxLength y mi filtro personalizado juntos mediante progtwigción. Algo como esto:

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

Para cualquier otra persona que se pregunte cómo lograr esto, aquí está mi clase EditTextNumeric extendida EditTextNumeric .

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

.setMaxValue(int) – límite de valor entero máximo

.setMin(int) – límite de valor entero mínimo

.getValue() – obtener un 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 otros métodos y atributos que se aplican a EditText , por supuesto también funcionan.

Debido a la observación de goto10, armé el siguiente código para protegerme contra perder otros filtros estableciendo 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 }); } } 
 //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()}); 

Otra forma de lograr esto es agregar la siguiente definición al archivo XML:

  

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

He tenido este problema y considero que nos falta una forma bien explicada de hacerlo de forma programática sin perder los filtros ya establecidos.

Establecer la longitud en XML:

Como afirma correctamente la respuesta aceptada, si desea definir una longitud fija a un EditText que no va a cambiar aún más en el futuro, simplemente defina en su XML de EditText:

 android:maxLength="10" 

Establecer la longitud programáticamente

Aquí está el problema, para establecer la longitud programáticamente necesitará configurar un InputFilter pero una vez que lo configure, todos los demás filtros desaparecerán (por ejemplo, maxLines, inputType, etc.). Para evitar perder filtros anteriores, debe obtener los filtros aplicados anteriormente, agregar maxLength y volver a establecer los filtros en EditText de la siguiente manera:

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

Esta es una clase de texto personalizado 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 }); } } } 

de manera simple en xml:

 android:maxLength="4" 

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

  

Esto funciona bien …

android:maxLength="10"

esto solo aceptará 10 caracteres.

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) 

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

1, longitud límite.
2, si ingresa más, dé una callback para activar su tostada.
3, el cursor puede estar en el medio o la cola.
4, el usuario puede ingresar pegando una cadena.
5, descartar siempre la entrada de desbordamiento y conservar 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, 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', marca '345' como resaltado y trata de pegar una cadena de '0000' que excederá la limitación.

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

Puedes usar android: maxLength = “10” en el texto de edición. (Aquí el límite es de hasta 10 caracteres)