web-dev-qa-db-fra.com

Android: Comment valider la saisie EditText?

Je dois effectuer une validation de saisie de formulaire sur une série de EditTexts. J'utilise OnFocusChangeListeners pour déclencher la validation après que l'utilisateur a saisi chacun d'entre eux, mais cela ne se comporte pas comme souhaité pour le dernier EditText.

Si je clique sur le bouton "Terminé" lors de la saisie dans l'EditText final, alors la méthode InputMethod est déconnectée, mais techniquement, le focus n'est jamais perdu sur l'EditText (et la validation ne se produit donc jamais).

Quelle est la meilleure solution?

Devrais-je surveiller lorsque InputMethod se dissocie de chaque EditText plutôt que lorsque la focalisation change? Si c'est le cas, comment?

163
Stefan

Pourquoi n'utilisez-vous pas TextWatcher?

Étant donné que vous devez valider un certain nombre de EditText boîtes, je pense que ce qui suit vous convient:

  1. Votre activité implémente l'interface Android.text.TextWatcher
  2. Vous ajoutez des écouteurs TextChanged à vos boîtes de dialogue EditText
txt1.addTextChangedListener(this);
txt2.addTextChangedListener(this);
txt3.addTextChangedListener(this);
  1. Parmi les méthodes remplacées, vous pouvez utiliser la méthode afterTextChanged(Editable s) comme suit
@Override
public void afterTextChanged(Editable s) {
    // validation code goes here
}

Le Editable s n'aide pas vraiment à trouver le texte de la zone de texte à modifier est modifié. Mais vous pouvez directement vérifier le contenu des cases EditText comme

String txt1String = txt1.getText().toString();
// Validate txt1String

dans la même méthode. J'espère que je suis clair et si je le suis, ça aide! :)

EDIT: Pour une approche plus propre, reportez-vous à réponse de Christopher Perry ci-dessous.

149
Nikhil

TextWatcher est un peu prolixe à mon goût, alors j'ai rendu quelque chose d'un peu plus facile à avaler:

public abstract class TextValidator implements TextWatcher {
    private final TextView textView;

    public TextValidator(TextView textView) {
        this.textView = textView;
    }

    public abstract void validate(TextView textView, String text);

    @Override
    final public void afterTextChanged(Editable s) {
        String text = textView.getText().toString();
        validate(textView, text);
    }

    @Override
    final public void beforeTextChanged(CharSequence s, int start, int count, int after) { /* Don't care */ }

    @Override
    final public void onTextChanged(CharSequence s, int start, int before, int count) { /* Don't care */ }
}

Il suffit de l'utiliser comme ceci:

editText.addTextChangedListener(new TextValidator(editText) {
    @Override public void validate(TextView textView, String text) {
       /* Validation code here */
    }
});
118
Christopher Perry

Si vous voulez des popups et des images de validation Nice en cas d'erreur, vous pouvez utiliser la méthode setError de la classe EditText telle que je la décris ici

Screenshot of the use of setError taken from Donn Felker, the author of the linked post

89
Donn Felker

Afin de réduire la verbosité de la logique de validation, j'ai créé un bibliothèque pour Android . Il prend en charge la plupart des validations quotidiennes à l'aide d'annotations et de règles intégrées. Il existe des contraintes telles que @TextRule, @NumberRule, @Required, @Regex, @Email, @IpAddress, @Password, etc.

Vous pouvez ajouter ces annotations à vos références de widgets d'interface utilisateur et effectuer des validations. Il vous permet également d'effectuer des validations de manière asynchrone, ce qui est idéal pour des situations telles que la vérification du nom d'utilisateur unique d'un serveur distant.

Il y a un exemple sur le page d'accueil du projet sur l'utilisation des annotations. Vous pouvez également lire le article de blog associé où j'ai écrit des exemples de codes sur la façon d'écrire des règles personnalisées pour les validations.

Voici un exemple simple qui décrit l’utilisation de la bibliothèque.

@Required(order = 1)
@Email(order = 2)
private EditText emailEditText;

@Password(order = 3)
@TextRule(order = 4, minLength = 6, message = "Enter at least 6 characters.")
private EditText passwordEditText;

@ConfirmPassword(order = 5)
private EditText confirmPasswordEditText;

@Checked(order = 6, message = "You must agree to the terms.")
private CheckBox iAgreeCheckBox;

La bibliothèque est extensible, vous pouvez écrire vos propres règles en étendant la classe Rule.

24
Ragunath Jawahar

C'était une bonne solution de ici

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++) { 
            String checkMe = String.valueOf(source.charAt(i));

            Pattern pattern = Pattern.compile("[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz123456789_]*");
            Matcher matcher = pattern.matcher(checkMe);
            boolean valid = matcher.matches();
            if(!valid){
                Log.d("", "invalid");
                return "";
            }
        } 
        return null; 
    } 
};

edit.setFilters(new InputFilter[]{filter}); 
11
Daniel Magnusson

Approche mise à jour - TextInputLayout:

Google a récemment lancé une bibliothèque de support à la conception. Il existe un composant appelé TextInputLayout . Il prend en charge l'affichage d'une erreur via setErrorEnabled(boolean) et setError(CharSequence).

Comment l'utiliser?

Étape 1: Enveloppez votre EditText avec TextInputLayout:

  <Android.support.design.widget.TextInputLayout
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:id="@+id/layoutUserName">

    <EditText
      Android:layout_width="match_parent"
      Android:layout_height="wrap_content"
      Android:hint="hint"
      Android:id="@+id/editText1" />

  </Android.support.design.widget.TextInputLayout>

Étape 2: Valider la saisie

// validating input on a button click
public void btnValidateInputClick(View view) {

    final TextInputLayout layoutUserName = (TextInputLayout) findViewById(R.id.layoutUserName);
    String strUsername = layoutLastName.getEditText().getText().toString();

    if(!TextUtils.isEmpty(strLastName)) {
        Snackbar.make(view, strUsername, Snackbar.LENGTH_SHORT).show();
        layoutUserName.setErrorEnabled(false);
    } else {
        layoutUserName.setError("Input required");
        layoutUserName.setErrorEnabled(true);
    }
}

J'ai créé un exemple sur mon référentiel Github , consultez l'exemple si vous le souhaitez!

9
Paresh Mayani

Je trouve InputFilter plus approprié pour valider les entrées de texte sous Android.

Voici un exemple simple: Comment utiliser InputFilter pour limiter les caractères dans un EditText sous Android?

Vous pouvez ajouter un Toast pour informer l'utilisateur de vos restrictions. Vérifiez également le tag Android: inputType.

7
Moisés

J'ai écrit une classe qui étend EditText, qui supporte nativement certaines méthodes de validation et est en réalité très flexible.

Actuellement, au moment où j'écris, en mode natif pris en charge via les méthodes de validation des attributs xml sont :

  1. alpha
  2. alphanumérique
  3. numérique
  4. expression rationnelle générique
  5. corde vide

Vous pouvez le vérifier ici

Je espère que vous l'apprécierez :)

7
Andrea Baccega

J'avais besoin d'effectuer une validation intra-champ et non une validation inter-champ pour vérifier que mes valeurs étaient des valeurs à virgule flottante non signées dans un cas et des valeurs à virgule flottante signées dans un autre. Voici ce qui semble fonctionner pour moi:

    <EditText
        Android:id="@+id/x" 
        Android:background="@Android:drawable/editbox_background" 
        Android:gravity="right" 
        Android:inputType="numberSigned|numberDecimal" 
    />

Notez que vous ne devez pas avoir d'espace dans "numberSigned | numberDecimal". Par exemple: "numberSigned | numberDecimal" ne fonctionnera pas. Je ne sais pas pourquoi.

6
user405821

Cela semble vraiment prometteur et correspond exactement à ce que la doc m'a commandé:

Validateur EditText

    public void onClickNext(View v) {
    FormEditText[] allFields    = { etFirstname, etLastname, etAddress, etZipcode, etCity };


    boolean allValid = true;
    for (FormEditText field: allFields) {
        allValid = field.testValidity() && allValid;
    }

    if (allValid) {
        // YAY
    } else {
        // EditText are going to appear with an exclamation mark and an explicative message.
    }
}

validateurs personnalisés plus ces construit dans:

  • regexp : pour les expressions rationnelles personnalisées
  • numérique : pour un champ uniquement numérique
  • alpha : pour un champ alpha uniquement
  • alphaNumeric : devinez quoi?
  • personName : vérifie si le texte saisi est un prénom ou un nom de famille.
  • personFullName : vérifie si la valeur entrée est un nom complet complet.
  • email : vérifie que le champ est un email valide
  • creditCard : vérifie que le champ contient une carte de crédit valide en utilisant algorithme de Luhn
  • phone : vérifie que le champ contient un numéro de téléphone valide
  • domainName : vérifie que le champ contient un nom de domaine valide (réussit toujours le test dans le niveau API <8)
  • ipAddress : vérifie que le champ contient une adresse IP valide.
  • webUrl : vérifie que le champ contient une URL valide (réussit toujours le test dans le niveau API <8)
  • date : vérifie que le champ est un format date/date/heure valide (si customFormat est défini, vérifie avec customFormat)
  • nocheck : Il ne vérifie rien sauf la vide du champ.
5
Abs

Dans le fichier main.xml

Vous pouvez mettre l'attribut suivant pour valider uniquement les caractères de l'alphabet pouvant être acceptés dans edittext.

Faire ceci:

  Android:entries="abcdefghijklmnopqrstuvwxyz"
3
KKumar

Vous pouvez obtenir le comportement souhaité en écoutant lorsque l'utilisateur appuie sur le bouton "Terminé" du clavier. Vous pouvez également consulter d'autres astuces sur l'utilisation d'EditText dans mon message "Validation de formulaire Android - de la bonne façon"

Exemple de code:

mTextView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
        if (actionId == EditorInfo.IME_ACTION_DONE) {                    
            validateAndSubmit();
            return true;
        }
        return false;
    }});  
2
zasadnyy

pour la validation de l'e-mail et du mot de passe, essayez

  if (isValidEmail(et_regemail.getText().toString())&&etpass1.getText().toString().length()>7){
      if (validatePassword(etpass1.getText().toString())) {
      Toast.makeText(getApplicationContext(),"Go Ahead".....
      }
      else{

       Toast.makeText(getApplicationContext(),"InvalidPassword".....
       }

}else{

 Toast.makeText(getApplicationContext(),"Invalid Email".....
}


public boolean validatePassword(final String password){
    Pattern pattern;
    Matcher matcher;
    final String PASSWORD_PATTERN = "^(?=.*[0-9])(?=.*[A-Z])(?=.* 
    [@#$%^&+=!])(?=\\S+$).{4,}$";
    pattern = Pattern.compile(PASSWORD_PATTERN);
    matcher = pattern.matcher(password);

    return matcher.matches();
}

public final static boolean isValidEmail(CharSequence target) {
    if (target == null)
        return false;

    return Android.util.Patterns.EMAIL_ADDRESS.matcher(target).matches();
}
0