Android: ¿Cómo puedo validar la entrada de EditText?

169

Necesito hacer una validación de entrada de formulario en una serie de EditTexts. Estoy usando OnFocusChangeListeners para activar la validación después de que el usuario escriba en cada uno, pero esto no se comporta como se desea para el último EditText.

Si hago clic en el botón "Listo" mientras escribo en el EditText final, entonces InputMethod se desconecta, pero técnicamente nunca se pierde el foco en EditText (y, por lo tanto, la validación nunca ocurre).

¿Cuál es la mejor solución?

¿Debería estar monitoreando cuando InputMethod se desvincula de cada EditText en lugar de cuando cambia el foco? ¿Si es así, cómo?

Stefan
fuente
1
¿Realmente necesita validar la entrada EditText al mismo tiempo que el usuario está escribiendo? ¿Por qué no simplemente valida los EditText una vez que el usuario hace clic en el botón Listo?
Cristian
Eso es exactamente lo que quiero: que el texto se verifique cuando el usuario haga clic en el botón Listo (por botón Listo me refiero al botón "Listo" en el QWERTY InputManager ... NO el botón de envío del formulario). Excepto que cuando presiono el botón Listo, el foco permanece en el último elemento del formulario y mi método de validación nunca se activa. Espero que mi redacción es clara ...
Stefan
La solución de @Cristian es exactamente lo que estaba buscando y la encuentro aquí: stackoverflow.com/questions/43013812/…
LampPost el
@Cristian Llego un poco tarde, pero estoy buscando una solución donde los EditText se validen mientras la persona está escribiendo. Tengo un formulario de inicio de sesión / registro y quiero mostrar el botón "Enviar" solo cuando los datos del formulario son válidos.
Zonker.in.Geneva

Respuestas:

154

¿Por qué no lo usas TextWatcher?

Dado que tiene una serie de EditTextcuadros para validar, creo que lo siguiente le conviene:

  1. Su actividad implementa la android.text.TextWatcherinterfaz
  2. Agregue oyentes TextChanged a sus cuadros EditText
txt1.addTextChangedListener(this);
txt2.addTextChangedListener(this);
txt3.addTextChangedListener(this);
  1. De los métodos anulados, puede usar el afterTextChanged(Editable s)método de la siguiente manera
@Override
public void afterTextChanged(Editable s) {
    // validation code goes here
}

La Editable srealidad no ayuda para encontrar lo que se está cambiando el texto del cuadro de EditarTexto. Pero puede verificar directamente el contenido de los cuadros EditText como

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

En el mismo método. Espero estar claro y si lo estoy, ¡ayuda! :)

EDITAR: Para un enfoque más limpio, consulte la respuesta de Christopher Perry a continuación.

Niks
fuente
3
Eso se ve exactamente como lo que necesito. No había oído hablar de TextWatcher (nuevo en el SDK / API), pero lo probaré y veré si se comporta como creo que lo hará. Gracias por la info!
Stefan
1
¡De nada! :) ahora que lo está validando, ¿podría compartir cómo informará al usuario del error de validación? Actualmente estoy buscando los mejores métodos para lo mismo.
Niks
Nikhil Patil, solo uso Toast para que el usuario sepa que ha hecho algo mal. ¿Hay alguna razón por la cual eso no será efectivo en su caso?
Yevgeny Simkin
55
Por supuesto, Toast es una forma natural en Android. Pero cuando tenemos una cantidad considerable de elementos en la pantalla que necesitan validación, las tostadas no parecen ser la opción correcta. (En mi humilde opinión, molestaría al usuario) He estado experimentando con TextView.setError () ( developer.android.com / reference / android / widget / ...
Niks
1
Aunque hay poco soporte en TextWatcher, funciona ... ¡un poco!
Tivie
126

TextWatcher es un poco detallado para mi gusto, así que hice algo un poco más fácil de tragar:

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

Solo úsalo así:

editText.addTextChangedListener(new TextValidator(editText) {
    @Override public void validate(TextView textView, String text) {
       /* Validation code here */
    }
});
Christopher Perry
fuente
44
@fremmedehenvendelser: cada EditTextIS-ATextView
Niks
2
increíble abstracción y uso de la clase abstracta
Saher Ahwal
1
@fullmeriffic probablemente no inicializó su EditText. Asegúrese de llamar addTextChangedListenerdespués de resolver el texto de edición desde la vista
Ghostli
1
@StephaneEybert Es una clase anónima
Christopher Perry
2
Principio de segregación de interfaz en la práctica
Maciej Beimcik
92

Si desea ventanas emergentes e imágenes de validación agradables cuando ocurre un error, puede usar el setErrormétodo de la EditTextclase como describo aquí

Captura de pantalla del uso de setError tomada de Donn Felker, el autor de la publicación vinculada

Donn Felker
fuente
¿Cómo se obtiene un TextWatcher para acceder a dos EditTexts? He agregado un TextWatcher con éxito a mi passwordConfirmTextField, pero necesito hacer referencia al otro passwordTextField, para poder compararlos. ¿Alguna sugerencia?
Zonker.in.Geneva
26

Para reducir la verbosidad de la lógica de validación, he creado una biblioteca para Android . Se encarga de la mayoría de las validaciones diarias mediante anotaciones y reglas integradas. Hay limitaciones tales como @TextRule, @NumberRule, @Required, @Regex, @Email, @IpAddress, @Password, etc,

Puede agregar estas anotaciones a sus referencias de widget de IU y realizar validaciones. También le permite realizar validaciones de forma asíncrona, lo que es ideal para situaciones como la verificación de un nombre de usuario único desde un servidor remoto.

Hay un ejemplo en la página de inicio del proyecto sobre cómo usar las anotaciones. También puede leer la publicación de blog asociada donde he escrito códigos de muestra sobre cómo escribir reglas personalizadas para validaciones.

Aquí hay un ejemplo simple que muestra el uso de la biblioteca.

@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 biblioteca es extensible, puede escribir sus propias reglas extendiendo la Ruleclase.

Ragunath Jawahar
fuente
Esta biblioteca funciona a las mil maravillas. ¿Pero las anotaciones @TextRule se eliminaron de la versión 2.0.3?
LTroya
1
Se ha reemplazado con la @Lengthanotación.
Ragunath Jawahar
@RagunathJawahar He notado que la validación no funciona si valida los datos entrantes, es decir, contacto, por lo que estoy tratando de validar el correo electrónico que proviene de Intención -> Contactos, pero una vez que me concentro en EditText y agrego / elimino cualquier texto y luego la validación funciona como validación también se llama en TextChange y validate () también se llama cuando recibimos datos de Contact.
Ronak Mehta
11

Esta fue una buena solución desde aquí

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}); 
Daniel Magnusson
fuente
¿Cómo lo uso junto con el espacio y no limito dos espacios uno al lado del otro?
chiru
10

Enfoque actualizado - TextInputLayout:

Google ha lanzado recientemente la biblioteca de soporte de diseño y hay un componente llamado TextInputLayout y admite mostrar un error a través de setErrorEnabled(boolean)y setError(CharSequence).

¿Cómo usarlo?

Paso 1: Envuelva su 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>

Paso 2: validar la entrada

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

He creado un ejemplo sobre mi repositorio de Github , ¡mira el ejemplo si lo deseas!

Paresh Mayani
fuente
La mejor respuesta, pero tuve que usar com.google.android.material.textfield.TextInputLayout(observe el cambio de material ). Lo obtuve de esta respuesta: stackoverflow.com/a/56753953/900394
Alaa M.
8

Escribí una clase que extiende EditText que admite de forma nativa algunos métodos de validación y que en realidad es muy flexible.

Actualmente, mientras escribo, los métodos de validación de atributos xml son nativamente compatibles :

  1. alfa
  2. alfanumérico
  3. numérico
  4. expresión genérica
  5. vacío de la cuerda

Puedes verlo aquí

Espero que lo disfrutes :)

Andrea Baccega
fuente
7

Creo que InputFilter es más apropiado para validar entradas de texto en Android.

Aquí hay un ejemplo simple: ¿Cómo uso InputFilter para limitar los caracteres en un EditText en Android?

Puede agregar un Brindis para informar al usuario sobre sus restricciones. También verifique la etiqueta android: inputType.

Moisés
fuente
1
Esta es una buena solución para cosas que se pueden validar a medida que escribe (entrada alfanumérica), pero no funcionaría para cosas que solo deberían validarse una vez que el usuario haya terminado de ingresar la entrada (dirección de correo electrónico).
Peter Ajtai
¿Cómo desencadenarías esa tostada? El filtro evita que cualquier textwatchers reaccione ... ¿Quizás con un onKeyListener?
abarcan el
Activé ese Toast con una condición IF del método filter () (en la clase InputFilter).
Moisés
6

Necesitaba hacer validación intracampo y no validación intercampo para probar que mis valores eran valores de coma flotante sin signo en un caso y valores de punto flotante con signo en otro. Esto es lo que parece funcionar para mí:

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

Tenga en cuenta que no debe tener espacios dentro de "numberSigned | numberDecimal". Por ejemplo: "numberSigned | numberDecimal" no funcionará. No estoy seguro de por qué.

usuario405821
fuente
5

Esto parece muy prometedor y justo lo que el doctor me ordenó:

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

validadores personalizados más estos integrados en:

  • regexp : para expresiones regulares personalizadas
  • numérico : para un solo campo numérico
  • alfa : para un campo solo alfa
  • alphaNumeric : ¿adivina qué?
  • personName : verifica si el texto ingresado es una persona nombre o apellido.
  • personFullName : verifica si el valor ingresado es un nombre completo completo.
  • correo electrónico : comprueba que el campo es un correo electrónico válido
  • creditCard : verifica que el campo contenga una tarjeta de crédito válida usando el algoritmo de Luhn
  • teléfono : comprueba que el campo contiene un número de teléfono válido
  • domainName : comprueba que el campo contiene un nombre de dominio válido (siempre pasa la prueba en el nivel de API <8)
  • ipAddress : verifica que el campo contenga una dirección IP válida
  • webUrl : comprueba que el campo contiene una URL válida (siempre pasa la prueba en el nivel de API <8)
  • fecha : verifica que el campo tenga un formato válido de fecha / fecha y hora (si se configura customFormat, verifica con customFormat)
  • nocheck : No verifica nada excepto el vacío del campo.
Abdominales
fuente
2

En el archivo main.xml

Puede poner el siguiente atributo para validar que solo los caracteres alfabéticos pueden aceptar en edittext.

Hacer esto :

  android:entries="abcdefghijklmnopqrstuvwxyz"
KKumar
fuente
2

Puede obtener el comportamiento deseado escuchando cuando el usuario presiona el botón "Listo" en el teclado, también consulte otros consejos sobre cómo trabajar con EditText en mi publicación "Validación de formulario de Android: la forma correcta"

Código de muestra:

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;
    }});  
zasadnyy
fuente
0

para la validación de correo electrónico y contraseña intente

  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();
}
Syed Danish Haider
fuente
-2

He creado esta biblioteca para Android donde puede validar un diseño de material EditText dentro y EditTextLayout fácilmente de esta manera:

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

entonces puedes usarlo así:

<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.*" />

Luego puede verificar si es válido así:

    ageSmartEditText.check()

Para obtener más ejemplos y personalización, consulte el repositorio https://github.com/TeleClinic/SmartEditText

Karim
fuente