Android: come posso validare l'input EditText?


169

Devo eseguire la convalida dell'input del modulo su una serie di EditTexts. Sto usando OnFocusChangeListeners per attivare la convalida dopo che l'utente ha digitato in ognuno, ma questo non si comporta come desiderato per l'ultimo EditText.

Se clicco sul pulsante "Fine" durante la digitazione nell'EditText finale, l'InputMethod viene disconnesso, ma tecnicamente il focus non viene mai perso sull'EditText (e quindi la validazione non si verifica mai).

Qual è la soluzione migliore?

Dovrei monitorare quando InputMethod si separa da ogni EditText piuttosto che quando lo stato attivo cambia? Se é cosi, come?


1
Hai davvero bisogno di convalidare l'input EditText mentre l'utente sta digitando? Perché non convalidi l'EditingText quando l'utente fa clic sul pulsante Fine?
Cristian,

È esattamente quello che voglio: per verificare il testo quando l'utente fa clic sul pulsante Fine (per pulsante Fine intendo il pulsante "Fine" sull'InputManager QWERTY ... NON il pulsante di invio del modulo). Tranne che quando premo il pulsante Fine, lo stato attivo rimane sull'ultimo elemento del modulo e il mio metodo di convalida non viene mai attivato. Spero che le mie parole siano chiare ...
Stefan,

Soluzione @Cristian 's è esattamente quello che stavo cercando e si trova qui: stackoverflow.com/questions/43013812/...
lampione

@Cristian Arriva un po 'in ritardo, ma sto cercando una soluzione in cui gli EditText siano validi mentre la persona sta scrivendo. Ho un modulo di accesso / registrazione e voglio mostrare il pulsante "Invia" solo quando i dati del modulo sono validi.
Zonker.in.Geneva,

Risposte:


154

Perché non usi TextWatcher?

Dal momento che hai un numero di EditTextcaselle da convalidare, penso che ti soddisferanno:

  1. La tua attività implementa l' android.text.TextWatcherinterfaccia
  2. Aggiungi listener TextChanged alle caselle Modifica testo
txt1.addTextChangedListener(this);
txt2.addTextChangedListener(this);
txt3.addTextChangedListener(this);
  1. Dei metodi sostituiti, è possibile utilizzare il afterTextChanged(Editable s)metodo come segue
@Override
public void afterTextChanged(Editable s) {
    // validation code goes here
}

La Editable srealtà non aiutano a trovare quale testo di dialogo EditText viene modificato. Ma puoi controllare direttamente il contenuto delle caselle EditText come

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

nello stesso metodo. Spero di essere chiaro e se lo sono, aiuta! :)

EDIT: per un approccio più pulito fare riferimento alla risposta di Christopher Perry di seguito.


3
Sembra esattamente quello di cui ho bisogno. Non avevo sentito parlare di TextWatcher (nuovo per SDK / API), ma lo proverò e vedrò se si comporta come penso. Grazie per le informazioni!
Stefan,

1
prego! :) ora che lo stai convalidando, potresti condividere come hai intenzione di informare l'utente del fallimento della convalida? Attualmente sto cercando i migliori metodi per lo stesso.
Niks,

Nikhil Patil, ho appena usato Toast per far sapere all'utente che hanno fatto qualcosa di sbagliato. C'è qualche motivo per cui non sarà efficace nel tuo caso?
Evgenij Simkin il

5
Naturalmente, Toast è un modo naturale su Android. Ma quando abbiamo una considerevole quantità di elementi sullo schermo che necessitano di convalida, i brindisi non sembrano essere la scelta corretta. (IMHO, disturberebbe l'utente) Ho sperimentato TextView.setError () ( developer.android.com / reference / android / widget /…
Niks,

1
Anche se c'è scarso supporto su TextWatcher, funziona ... un po '!
Tivie,

126

TextWatcher è un po 'prolisso per i miei gusti, quindi ho reso qualcosa di più facile da ingoiare:

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 */ }
}

Usalo in questo modo:

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

4
@fremmedehenvendelser: ogni EditTextIS-ATextView
Niks,

2
fantastica astrazione e uso della classe astratta
Saher Ahwal,

1
@fullmeriffic molto probabilmente non hai inizializzato il tuo EditText. Assicurati di chiamare addTextChangedListenerdopo aver risolto il tuo edittext dalla vista
Ghostli

1
@StephaneEybert È una classe anonima
Christopher Perry,

2
Principio di segregazione dell'interfaccia in pratica
Maciej Beimcik,

92

Se desideri visualizzare popup e immagini di convalida quando si verifica un errore, puoi utilizzare il setErrormetodo della EditTextclasse come descritto qui

Schermata dell'uso di setError presa da Donn Felker, l'autore del post collegato


Come si ottiene un TextWatcher per accedere a due EditTexts? Ho aggiunto con successo un TextWatcher al mio passwordConfirmTextField, ma devo fare riferimento all'altro passwordTextField, in modo da poterli confrontare. Eventuali suggerimenti?
Zonker.in.Geneva,

26

Al fine di ridurre la verbosità della logica di validazione, ho creato una libreria per Android . Si occupa della maggior parte delle convalide quotidiane utilizzando Annotazioni e regole integrate. Ci sono vincoli, come @TextRule, @NumberRule, @Required, @Regex, @Email, @IpAddress, @Password, ecc,

È possibile aggiungere queste annotazioni ai riferimenti del widget dell'interfaccia utente ed eseguire convalide. Inoltre, consente di eseguire convalide in modo asincrono, il che è l'ideale per situazioni come la ricerca di un nome utente univoco da un server remoto.

C'è un esempio nella home page del progetto su come usare le annotazioni. Puoi anche leggere il post sul blog associato in cui ho scritto dei codici di esempio su come scrivere regole personalizzate per le convalide.

Ecco un semplice esempio che descrive l'utilizzo della libreria.

@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 libreria è estensibile, puoi scrivere le tue regole estendendo la Ruleclasse.


Questa libreria funziona come un fascino. Ma le annotazioni @TextRule sono state rimosse dalla versione 2.0.3?
LTroya,

1
È stato sostituito con l' @Lengthannotazione.
Ragunath Jawahar,

@RagunathJawahar Ho notato che la convalida non funziona se convalidi i dati in arrivo, vale a dire il contatto, quindi sto provando a convalidare la posta elettronica che proviene da Intent -> Contatti, ma una volta che mi concentro su EditText e aggiungi / elimina qualsiasi testo, quindi la convalida funziona come la convalida viene anche chiamata su TextChange e validate () viene anche chiamato quando riceviamo i dati dal contatto.
Ronak Mehta,

11

Questa è stata una bella soluzione da qui

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

come lo uso insieme allo spazio e non limito due spazi uno accanto all'altro?
Chiru,

10

Approccio aggiornato - TextInputLayout:

Google ha recentemente lanciato la libreria di supporto alla progettazione e esiste un componente chiamato TextInputLayout e supporta la visualizzazione di un errore tramite setErrorEnabled(boolean)e setError(CharSequence).

Come usarlo?

Passaggio 1: avvolgi il tuo EditText con 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>

Passaggio 2: convalida dell'input

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

Ho creato un esempio sul mio repository Github , controlla l'esempio se lo desideri!


Migliore risposta, ma ho dovuto usare com.google.android.material.textfield.TextInputLayout(notare il cambiamento materiale ). Capito da questa risposta: stackoverflow.com/a/56753953/900394
Alaa M.

8

Ho scritto una classe che estende EditText che supporta nativamente alcuni metodi di validazione ed è in realtà molto flessibile.

Attualmente, mentre scrivo, supportati nativamente attraverso i metodi di convalida degli attributi xml sono:

  1. alfa
  2. alfanumerico
  3. numerico
  4. regexp generico
  5. vuoto della stringa

Puoi dare un'occhiata qui

Spero ti sia piaciuto :)


7

Trovo InputFilter più appropriato per convalidare input di testo su Android.

Ecco un semplice esempio: come posso usare InputFilter per limitare i caratteri in un EditText in Android?

È possibile aggiungere un brindisi per dare un feedback all'utente sulle restrizioni. Controlla anche il tag android: inputType.


1
Questa è una buona soluzione per cose che possono essere validate mentre digiti (input alfanumerico), ma non funzionerebbe per cose che dovrebbero essere validate solo una volta che l'utente ha finito di inserire l'input (indirizzo email).
Peter Ajtai,

Come scateneresti quel toast? Il filtro impedisce a qualsiasi osservatore di testi di reagire ... Forse con un onKeyListener?
durata

Ho attivato quel Toast con una condizione IF dal metodo filter () (nella classe InputFilter).
Moisés,

6

Avevo bisogno di fare la validazione tra campi e non quella tra campi per verificare che i miei valori fossero valori in virgola mobile senza segno in un caso e valori in virgola mobile con segno in un altro. Ecco cosa sembra funzionare per me:

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

Nota, non devi avere spazi all'interno di "numberSigned | numberDecimal". Ad esempio: "numberSigned | numberDecimal" non funzionerà. Non sono sicuro del perché.


5

Questo sembra davvero promettente e proprio quello che il documento ha ordinato per me:

EditText Validator

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

validatori personalizzati più questi integrati:

  • regexp : per regexp personalizzato
  • numerico : per un solo campo numerico
  • alfa : per un campo solo alfa
  • alphaNumeric : indovina un po '?
  • personName : controlla se il testo inserito è una persona nome o cognome.
  • personFullName : controlla se il valore inserito è un nome completo completo.
  • e-mail : verifica che il campo sia un'e-mail valida
  • creditCard : verifica che il campo contenga una carta di credito valida utilizzando Luhn Algorithm
  • telefono : verifica che il campo contenga un numero di telefono valido
  • domainName : controlla che il campo contenga un nome di dominio valido (supera sempre il test in API Level <8)
  • ipAddress : verifica che il campo contenga un indirizzo IP valido
  • webUrl : verifica che il campo contenga un URL valido (supera sempre il test nel Livello API <8)
  • data : controlla che il campo sia un formato data / data valido (se è impostato customFormat, controlla con customFormat)
  • nocheck : non controlla nulla tranne lo spazio vuoto del campo.

2

Nel file main.xml

È possibile inserire il seguente attrubute per convalidare solo caratteri alfabetici che possono essere accettati in edittext.

Fai questo :

  android:entries="abcdefghijklmnopqrstuvwxyz"

2

Puoi ottenere il comportamento desiderato ascoltando quando l'utente preme il pulsante "Fine" sulla tastiera, controlla anche altri suggerimenti su come lavorare con EditText nel mio post "Convalida del modulo Android - la strada giusta"

Codice di esempio:

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

0

per la convalida di e-mail e password provare

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

-2

Ho creato questa libreria per Android in cui è possibile convalidare un design del materiale EditText all'interno e EditTextLayout facilmente in questo modo:

    compile 'com.github.TeleClinic:SmartEditText:0.1.0'

allora puoi usarlo in questo modo:

<com.teleclinic.kabdo.smartmaterialedittext.CustomViews.SmartEditText
    android:id="@+id/passwordSmartEditText"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:setLabel="Password"
    app:setMandatoryErrorMsg="Mandatory field"
    app:setPasswordField="true"
    app:setRegexErrorMsg="Weak password"
    app:setRegexType="MEDIUM_PASSWORD_VALIDATION" />

<com.teleclinic.kabdo.smartmaterialedittext.CustomViews.SmartEditText
    android:id="@+id/ageSmartEditText"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:setLabel="Age"
    app:setMandatoryErrorMsg="Mandatory field"
    app:setRegexErrorMsg="Is that really your age :D?"
    app:setRegexString=".*\\d.*" />

Quindi puoi verificare se è valido in questo modo:

    ageSmartEditText.check()

Per ulteriori esempi e personalizzazioni consultare il repository https://github.com/TeleClinic/SmartEditText

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.