Quelle est la meilleure façon de limiter la longueur du texte de EditText dans Android

702

Quelle est la meilleure façon de limiter la longueur du texte d'un EditTextdans Android?

Existe-t-il un moyen de le faire via xml?

hpique
la source
1
Je voulais définir le nombre maximum de caractères pour mon EditText. Au début, il n'était pas évident que la limite de longueur de texte était la même chose. (Juste une note pour un autre voyageur confus).
Katedral Pillon
La bonne réponse est ici : stackoverflow.com/a/19222238/276949 . Cette réponse limite la longueur ET empêche un tampon de se remplir continuellement après avoir atteint la limite, permettant ainsi à votre clé de retour arrière de fonctionner correctement.
Martin Konecny

Réponses:

1381

Documentation

Exemple

android:maxLength="10"
Austin Hanson
la source
26
Oh! La même chose m'est arrivée. Je regardais le code, et il n'y a pas de méthode setMaxLength.
hpique
1
que fait la vérification ici? Il renvoie simplement à cette page.
qu'est
5
@Vincy, vous avez tort. La maxLengthpropriété fonctionne toujours.
ashishduh
6
Sachez que cela android:maxLengthéquivaut à InputFilter.LengthFilter, donc lorsque vous modifiez par programme son filtre, vous avez également modifié son filtre XML.
mr5
20
Pour les personnes qui disent que cela ne fonctionne pas, sachez que l'appel setFilterscessera de android:maxLengthfonctionner, car il écrase le filtre défini par le XML. En d'autres termes, si vous définissez des filtres par programme, vous devez les définir tous par programme.
Ian Newson
339

utilisez un filtre d'entrée pour limiter la longueur maximale d'une vue de texte.

TextView editEntryView = new TextView(...);
InputFilter[] filterArray = new InputFilter[1];
filterArray[0] = new InputFilter.LengthFilter(8);
editEntryView.setFilters(filterArray);
jerry
la source
5
C'est très utile si quelqu'un en a déjà fait InputFilter. Il remplace le android:maxlengthfichier xml, nous devons donc l'ajouter de LengthFiltercette façon.
Seblis
Je pense que votre réponse est la meilleure réponse, car elle est plus dynamique, +1
Muhannad A.Alhariri
197
EditText editText = new EditText(this);
int maxLength = 3;    
editText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(maxLength)});
Emran Hamza
la source
Ceci est similaire à la façon dont Android le fait avec le xml.
Nicolas Tyler
4
Comment puis-je définir une longueur minimale?
Akhila Madari
@AkhilaMadari, probablement avec TextWatcher.
CoolMind
65

Une note pour les personnes qui utilisent déjà un filtre d'entrée personnalisé et qui souhaitent également limiter la longueur maximale:

Lorsque vous affectez des filtres d'entrée dans le code, tous les filtres d'entrée précédemment définis sont effacés, y compris un ensemble avec android:maxLength. J'ai découvert cela en essayant d'utiliser un filtre d'entrée personnalisé pour empêcher l'utilisation de certains caractères que nous n'autorisons pas dans un champ de mot de passe. Après avoir défini ce filtre avec setFilters, la longueur max n'a plus été observée. La solution consistait à définir maxLength et mon filtre personnalisé ensemble par programme. Quelque chose comme ça:

myEditText.setFilters(new InputFilter[] {
        new PasswordCharFilter(), new InputFilter.LengthFilter(20)
});
goto10
la source
5
Vous pouvez d'abord récupérer les filtres existants comme, InputFilter [] existingFilters = editText.getFilters (); Ajoutez ensuite votre filtre avec ces filtres existants
subair_a
39
TextView tv = new TextView(this);
tv.setFilters(new InputFilter[]{ new InputFilter.LengthFilter(250) });
ramo2712
la source
7
Bien sûr, uniquement pour Android
VAdaihiep
27

J'ai eu ce problème et je considère qu'il nous manque une façon bien expliquée de le faire par programme sans perdre les filtres déjà définis.

Définition de la longueur en XML:

Comme la réponse acceptée l'indique correctement, si vous voulez définir une longueur fixe à un EditText que vous ne changerez plus à l'avenir, définissez simplement dans votre XML EditText:

android:maxLength="10" 

Définition de la longueur par programmation

Pour définir la longueur par programme, vous devrez la définir via un InputFilter. Mais si vous créez un nouveau InputFilter et le définissez sur le, EditTextvous perdrez tous les autres filtres déjà définis (par exemple maxLines, inputType, etc.) que vous pourriez avoir ajoutés via XML ou par programme.

C'est donc faux :

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

Pour éviter de perdre les filtres ajoutés précédemment, vous devez obtenir ces filtres, ajoutez le nouveau (maxLength dans ce cas) et redéfinissez les filtres EditTextcomme suit:

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 a cependant rendu la tâche plus facile pour tout le monde, vous devez également ajouter le filtre à ceux déjà existants, mais vous pouvez y parvenir avec un simple:

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

Pour tous ceux qui se demandent comment y parvenir, voici ma EditTextclasse étendue EditTextNumeric.

.setMaxLength(int) - définit le nombre maximum de chiffres

.setMaxValue(int) - limiter la valeur entière maximale

.setMin(int) - limiter la valeur entière minimale

.getValue() - obtenir une valeur entière

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

Exemple d'utilisation:

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

Toutes les autres méthodes et attributs qui s'appliquent à EditText, bien sûr, fonctionnent également.

Martynas Januškauskas
la source
1
Ce serait mieux si nous ajoutons ceci dans la mise en page XML. Je reçois une erreur avec cela lors de l'utilisation de xml Causé par: android.view.InflateException: ligne de fichier XML binaire # 47: Erreur lors du gonflement de la classe com.passenger.ucabs.utils.EditTextNumeric
Shihab Uddin
@Martynas Vous avez la même erreur que Shihab_returns, une solution?
Pranaysharma
17

En raison de l'observation de goto10, j'ai rassemblé le code suivant pour protéger contre la perte d'autres filtres en définissant la longueur maximale:

/**
 * 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
la source
3
Vous voudrez peut-être mettre à jour légèrement le code. Le tableau alloué doit être curFilters.length + 1 en taille et après avoir créé newFilters, vous n'avez pas défini "this" sur le tableau nouvellement alloué. 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
la source
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
la source
8

Vous pouvez également y parvenir en ajoutant la définition suivante au fichier 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"/>

Cela limitera la longueur maximale du EditTextwidget à 6 caractères.

user2586194
la source
6

De material.io , vous pouvez utiliser TextInputEditTextcombiné avec 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>

Vous pouvez configurer un mot de passe EditText avec drawable:

exemple de mot de passe

Ou vous pouvez limiter la longueur du texte avec / sans compteur:

contre-exemple

Dépendance:

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

XML

android:maxLength="10"

Par programme:

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

Remarque: en interne, EditText & TextView analysent la valeur de android:maxLengthXML et l'utilisent InputFilter.LengthFilter()pour l'appliquer.

Voir: TextView.java # L1564

nhoxbypass
la source
2

Il s'agit d'une classe EditText personnalisée qui permet au filtre Longueur de cohabiter avec d'autres filtres. Merci à la réponse de Tim Gallagher (ci-dessous)

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
la source
2

de manière simple en xml:

android:maxLength="4"

si vous avez besoin de définir 4 caractères dans le texte d'édition XML, utilisez-le

<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
la source
2

Cela fonctionne bien ...

android:maxLength="10"

cela n'acceptera que les 10caractères.

Sanjay Kumaar
la source
2

Essayez ceci pour Java par programme :

myEditText(new InputFilter[] {new InputFilter.LengthFilter(CUSTOM_MAX_LEN)});
reza_khalafi
la source
1
Vous avez oublié d'appeler la méthode pour qu'elle ressemble à myEditText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(CUSTOM_MAX_LEN)});
ceci
1

J'avais vu beaucoup de bonnes solutions, mais je voudrais donner ce que je pense être une solution plus complète et conviviale, qui comprend:

1, longueur limite.
2, Si vous saisissez plus, donnez un rappel pour déclencher votre toast.
3, le curseur peut être au milieu ou à la queue.
4, l'utilisateur peut entrer en collant une chaîne.
5, Jetez toujours l'entrée de débordement et conservez l'origine.

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

Ce que j'ai échoué, c'est que si l'utilisateur met en surbrillance une partie de l'entrée actuelle et essaie de coller une chaîne très longue, je ne sais pas comment restaurer la surbrillance.

Tels que, la longueur maximale est définie sur 10, l'utilisateur a saisi «12345678», et marque «345» comme surbrillance, et essayez de coller une chaîne de «0000» qui dépassera la limitation.

Lorsque j'essaie d'utiliser edit_text.setSelection (start = 2, end = 4) pour restaurer le statut d'origine, le résultat est, il suffit d'insérer 2 espaces en tant que '12 345 678 ', pas la surbrillance d'origine. J'aimerais que quelqu'un résolve ça.

hyyou2010
la source
1

Vous pouvez utiliser android:maxLength="10"dans EditText. (Ici, la limite est jusqu'à 10 caractères)

Jocelin
la source
0

Kotlin:

edit_text.filters += InputFilter.LengthFilter(10)

ZTE Blade A520a un effet étrange. Lorsque vous tapez plus de 10 symboles (par exemple, 15), EditTextaffiche les 10 premiers, mais les 5 autres ne sont ni visibles ni accessibles. Mais lorsque vous supprimez des symboles avec Backspace, il supprime d'abord les 5 bons symboles, puis supprime les 10 restants. Pour contourner ce problème, utilisez une solution :

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

ou ca:

android:inputType="textNoSuggestions"

ou ceci, si vous voulez avoir des suggestions:

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
la source
0

de manière simple en xml:

android:maxLength="@{length}"

pour le paramétrer, vous pouvez utiliser la fonction suivante

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
la source