web-dev-qa-db-fra.com

Comment utiliser InputFilter pour limiter les caractères dans un EditText sous Android?

Je veux restreindre les caractères à 0-9, a-z, A-Z et barre d'espace uniquement. La définition du type d’entrée que je peux limiter aux chiffres est impossible, mais je ne peux pas comprendre la façon dont Inputfilter examine les documents.

166
Tim Wayne

J'ai trouvé ceci sur un autre forum. Fonctionne comme un champion.

InputFilter filter = new InputFilter() {
    public CharSequence filter(CharSequence source, int start, int end,
            Spanned dest, int dstart, int dend) {
        for (int i = start; i < end; i++) {
            if (!Character.isLetterOrDigit(source.charAt(i))) {
                return "";
            }
        }
        return null;
    }
};
edit.setFilters(new InputFilter[] { filter });
180
moonlightcheese

Les InputFilters sont un peu compliqués dans les versions de Android qui affichent des suggestions de dictionnaires. Vous obtenez parfois un SpannableStringBuilder, parfois un simple String dans le paramètre source.

Le InputFilter suivant devrait fonctionner. N'hésitez pas à améliorer ce code!

new InputFilter() {
    @Override
    public CharSequence filter(CharSequence source, int start, int end,
            Spanned dest, int dstart, int dend) {

        if (source instanceof SpannableStringBuilder) {
            SpannableStringBuilder sourceAsSpannableBuilder = (SpannableStringBuilder)source;
            for (int i = end - 1; i >= start; i--) { 
                char currentChar = source.charAt(i);
                 if (!Character.isLetterOrDigit(currentChar) && !Character.isSpaceChar(currentChar)) {    
                     sourceAsSpannableBuilder.delete(i, i+1);
                 }     
            }
            return source;
        } else {
            StringBuilder filteredStringBuilder = new StringBuilder();
            for (int i = start; i < end; i++) { 
                char currentChar = source.charAt(i);
                if (Character.isLetterOrDigit(currentChar) || Character.isSpaceChar(currentChar)) {    
                    filteredStringBuilder.append(currentChar);
                }     
            }
            return filteredStringBuilder.toString();
        }
    }
}
130
Łukasz Sromek

beaucoup plus facile:

<EditText
    Android:inputType="text"
    Android:digits="0,1,2,3,4,5,6,7,8,9,*,qwertzuiopasdfghjklyxcvbnm" />
103
Florian Fröhlich

Aucune des réponses postées n'a fonctionné pour moi. Je suis venu avec ma propre solution:

InputFilter filter = new InputFilter() {
    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        boolean keepOriginal = true;
        StringBuilder sb = new StringBuilder(end - start);
        for (int i = start; i < end; i++) {
            char c = source.charAt(i);
            if (isCharAllowed(c)) // put your condition here
                sb.append(c);
            else
                keepOriginal = false;
        }
        if (keepOriginal)
            return null;
        else {
            if (source instanceof Spanned) {
                SpannableString sp = new SpannableString(sb);
                TextUtils.copySpansFrom((Spanned) source, start, sb.length(), null, sp, 0);
                return sp;
            } else {
                return sb;
            }           
        }
    }

    private boolean isCharAllowed(char c) {
        return Character.isLetterOrDigit(c) || Character.isSpaceChar(c);
    }
}
editText.setFilters(new InputFilter[] { filter });
62
Kamil Seweryn

Utilisez ceci son travail 100% votre besoin et très simple.

<EditText
Android:inputType="textFilter"
Android:digits="@string/myAlphaNumeric" />

Dans strings.xml

<string name="myAlphaNumeric">abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</string>
23
Mohamed Ibrahim

Pour éviter les caractères spéciaux dans le type d'entrée

public static InputFilter filter = new InputFilter() {
    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        String blockCharacterSet = "~#^|$%*!@/()-'\":;,?{}=!$^';,?×÷<>{}€£¥₩%~`¤♡♥_|《》¡¿°•○●□■◇◆♧♣▲▼▶◀↑↓←→☆★▪:-);-):-D:-(:'(:O 1234567890";
        if (source != null && blockCharacterSet.contains(("" + source))) {
            return "";
        }
        return null;
    }
};

Vous pouvez définir le filtre à votre texte d'édition comme ci-dessous

edtText.setFilters(new InputFilter[] { filter });
15
user1414160

En plus de la réponse acceptée, il est également possible d'utiliser par exemple: Android:inputType="textCapCharacters" comme attribut de <EditText> afin de n'accepter que les caractères majuscules (et les nombres).

7
mblenton

C’est bien, le meilleur moyen de le corriger dans la mise en page XML elle-même en utilisant:

<EditText
Android:inputType="text"
Android:digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" />

comme l'a souligné à juste titre Florian Fröhlich, cela fonctionne bien pour les vues de texte même.

<TextView
Android:inputType="text"
Android:digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" />

Juste un mot d'avertissement, les caractères mentionnés dans le Android:digits ne seront affichés que, alors veillez à ne rater aucun jeu de caractères :)

5
Kailas

Pour une raison quelconque, le constructeur de la classe Android.text.LoginFilter est défini sur le paquet, de sorte que vous ne pouvez pas l'étendre directement (même s'il serait identique à ce code). Mais vous pouvez étendre LoginFilter.UsernameFilterGeneric! Ensuite, vous avez juste ceci:

class ABCFilter extends LoginFilter.UsernameFilterGeneric {
    public UsernameFilter() {
        super(false); // false prevents not-allowed characters from being appended
    }

    @Override
    public boolean isAllowed(char c) {
        if ('A' <= c && c <= 'C')
            return true;
        if ('a' <= c && c <= 'c')
            return true;

        return false;
    }
}

Ce n'est pas vraiment documenté, mais cela fait partie de la bibliothèque principale, et la source est simple . Je l'utilise depuis un moment, jusqu'à présent, pas de problème, bien que j'avoue que je n'ai jamais essayé de faire quelque chose de complexe impliquant des spannables.

5
Groxx

Cette solution simple fonctionnait pour moi lorsque je devais empêcher l'utilisateur de saisir des chaînes vides dans un EditText. Vous pouvez bien sûr ajouter plus de caractères:

InputFilter textFilter = new InputFilter() {

@Override

public CharSequence filter(CharSequence c, int arg1, int arg2,

    Spanned arg3, int arg4, int arg5) {

    StringBuilder sbText = new StringBuilder(c);

    String text = sbText.toString();

    if (text.contains(" ")) {    
        return "";   
    }    
    return c;   
    }   
};

private void setTextFilter(EditText editText) {

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

}
4

C'est un vieux fil de discussion, mais les solutions proposées ont toutes des problèmes (en fonction du périphérique/Android version/du clavier).

APPROCHE DIFFÉRENTE

Alors finalement, j’ai opté pour une approche différente, au lieu d’utiliser l’implémentation problématique de InputFilter, j’utilise TextWatcher et le TextChangedListener de EditText.

CODE COMPLET (EXEMPLE)

editText.addTextChangedListener(new TextWatcher() {

    @Override
    public void afterTextChanged(Editable editable) {
        super.afterTextChanged(editable);

        String originalText = editable.toString();
        int originalTextLength = originalText.length();
        int currentSelection = editText.getSelectionStart();

        // Create the filtered text
        StringBuilder sb = new StringBuilder();
        boolean hasChanged = false;
        for (int i = 0; i < originalTextLength; i++) {
            char currentChar = originalText.charAt(i);
            if (isAllowed(currentChar)) {
                sb.append(currentChar);
            } else {
                hasChanged = true;
                if (currentSelection >= i) {
                    currentSelection--;
                }
            }
        }

        // If we filtered something, update the text and the cursor location
        if (hasChanged) {
            String newText = sb.toString();
            editText.setText(newText);
            editText.setSelection(currentSelection);
        }
    }

    private boolean isAllowed(char c) {
        // TODO: Add the filter logic here
        return Character.isLetter(c) || Character.isSpaceChar(c);
    }
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        // Do Nothing
    }

    @Override
    onTextChanged(CharSequence s, int start, int before, int count) {
        // Do Nothing
    }
});

La raison pour laquelle InputFilter n’est pas une bonne solution dans Android est qu’elle dépend de l’implémentation du clavier. L'entrée du clavier est filtrée avant que l'entrée ne soit transmise à la variable EditText. Mais comme certains claviers ont des implémentations différentes pour l'invocation InputFilter.filter(), cela pose problème.

D'autre part, TextWatcher ne se soucie pas de l'implémentation du clavier, cela nous permet de créer une solution simple et de nous assurer que cela fonctionnera sur tous les périphériques.

1
Eyal Biran

En ignorant les éléments de span que d'autres personnes ont traités, pour gérer correctement les suggestions de dictionnaire, j'ai trouvé que le code suivant fonctionnait.

La source augmente au fur et à mesure que la suggestion augmente, nous devons donc déterminer le nombre de caractères que nous attendons réellement de notre part avant de renvoyer quoi que ce soit.

Si nous n'avons pas de caractères non valides, retourne null pour que le remplacement par défaut se produise.

Sinon, nous devons extraire les caractères valides de la sous-chaîne qui sera ACTUELLEMENT placée dans le EditText.

InputFilter filter = new InputFilter() { 
    public CharSequence filter(CharSequence source, int start, int end, 
    Spanned dest, int dstart, int dend) { 

        boolean includesInvalidCharacter = false;
        StringBuilder stringBuilder = new StringBuilder();

        int destLength = dend - dstart + 1;
        int adjustStart = source.length() - destLength;
        for(int i=start ; i<end ; i++) {
            char sourceChar = source.charAt(i);
            if(Character.isLetterOrDigit(sourceChar)) {
                if(i >= adjustStart)
                     stringBuilder.append(sourceChar);
            } else
                includesInvalidCharacter = true;
        }
        return includesInvalidCharacter ? stringBuilder : null;
    } 
}; 
1

empêcher les mots dans edittext. créer une classe que vous pourriez utiliser à tout moment.

public class Wordfilter implements InputFilter
{
    @Override
    public CharSequence filter(CharSequence source, int start, int end,Spanned dest, int dstart, int dend) {
        // TODO Auto-generated method stub
        boolean append = false;
        String text = source.toString().substring(start, end);
        StringBuilder str = new StringBuilder(dest.toString());
        if(dstart == str.length())
        {
            append = true;
            str.append(text);
        }
        else
            str.replace(dstart, dend, text);
        if(str.toString().contains("aaaaaaaaaaaa/*the Word here*/aaaaaaaa"))
        {
            if(append==true)
                return "";
            else
                return dest.subSequence(dstart, dend);
        }
        return null;
    }
}
1
Sahar Millis

Si vous sous-classez InputFilter, vous pouvez créer votre propre InputFilter qui filtrera tous les caractères non alphanumériques.

L’interface InputFilter a une méthode, filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend), et elle vous fournit toutes les informations nécessaires sur les caractères entrés dans le texte d’édition lui étant attribué.

Une fois que vous avez créé votre propre InputFilter, vous pouvez l'affecter à EditText en appelant setFilters (...).

http://developer.Android.com/reference/Android/text/InputFilter.html#filter (Java.lang.CharSequence , int, int, Android.text.Spanned, int, int)

1
nicholas.hauschild

si vous souhaitez également inclure un espace dans votre entrée, ajoutez un espace dans Android: code du chiffre comme indiqué ci-dessus.

Cela fonctionne bien pour moi, même dans la version ci-dessus Android 4.0.

prendre plaisir :)

0
Ujjwal

Il est possible d'utiliser setOnKeyListener. Dans cette méthode, nous pouvons personnaliser l'entrée edittext!

0
Võ Hoài Lên