Android: como posso validar a entrada EditText?

169

Eu preciso fazer a validação de entrada de formulário em uma série de EditTexts. Estou usando o OnFocusChangeListeners para disparar a validação após o usuário digitar em cada um, mas isso não se comporta conforme o desejado para o último EditText.

Se eu clicar no botão "Concluído" enquanto digito o EditText final, o InputMethod é desconectado, mas tecnicamente o foco nunca é perdido no EditText (e a validação nunca ocorre).

Qual a melhor solução?

Devo monitorar quando o InputMethod se desconecta de cada EditText e não quando o foco muda? Se sim, como?

Stefan
fonte
1
Você realmente precisa validar a entrada EditText ao mesmo tempo em que o usuário está digitando? Por que você não apenas valida os EditTexts quando o usuário clica no botão Concluído?
Cristian
É exatamente isso que eu quero: que o texto seja verificado quando o usuário clicar no botão Concluído (por botão Concluído, quero dizer o botão "Concluído" no QWERTY InputManager ... NÃO no botão de envio do formulário). Exceto que, quando pressiono o botão Concluído, o foco permanece no último elemento do formulário e meu método de validação nunca é acionado. Espero que o meu texto é claro ...
Stefan
Solução @Cristian 's é exatamente o que eu estava procurando e é encontrado aqui: stackoverflow.com/questions/43013812/...
poste
@ Cristian Chegando um pouco tarde, mas estou procurando uma solução em que os EditText sejam validados enquanto a pessoa está digitando. Tenho um formulário de login / registro e quero mostrar o botão "Enviar" somente quando os dados do formulário são válidos.
Zonker.in.Geneva 20/04

Respostas:

154

Por que você não usa TextWatcher?

Como você tem um número de EditTextcaixas a serem validadas, acho que o seguinte deve atender a você:

  1. Sua atividade implementa android.text.TextWatcherinterface
  2. Você adiciona ouvintes TextChanged às caixas EditText
txt1.addTextChangedListener(this);
txt2.addTextChangedListener(this);
txt3.addTextChangedListener(this);
  1. Dos métodos substituídos, você pode usar o afterTextChanged(Editable s)método da seguinte maneira
@Override
public void afterTextChanged(Editable s) {
    // validation code goes here
}

O Editable srealmente não ajuda a descobrir qual o texto de caixa EditText está sendo alterado. Mas você pode verificar diretamente o conteúdo das caixas EditText, como

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

no mesmo método. Espero estar claro e, se estiver, ajuda! :)

EDIT: Para uma abordagem mais limpa, consulte a resposta de Christopher Perry abaixo.

Niks
fonte
3
Parece exatamente o que eu preciso. Não tinha ouvido falar do TextWatcher (novo no SDK / API), mas vou testá-lo e ver se ele se comporta da maneira que penso que será. Obrigado pela informação!
Stefan
1
de nada! :) agora que você está validando, você pode compartilhar como informar o usuário sobre a falha na validação? Atualmente, estou procurando os melhores métodos para o mesmo.
Niks
Nikhil Patil, eu apenas uso o Toast para informar ao usuário que eles fizeram algo errado. Existe alguma razão para que isso não seja eficaz no seu caso?
Yevgeny Simkin
5
Claro, o Toast é uma maneira natural no Android. Mas quando temos uma quantidade considerável de elementos na tela que precisam de validação, as brindes não parecem ser a escolha correta. (IMHO, isso incomodaria o usuário) Eu tenho experimentado o TextView.setError () ( developer.android.com / reference / android / widget /…
Niks
1
Embora exista um suporte insuficiente no TextWatcher, ele funciona ... meio!
Tivie
126

O TextWatcher é um pouco detalhado para o meu gosto, então eu facilitei algo de engolir:

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

Apenas use-o assim:

editText.addTextChangedListener(new TextValidator(editText) {
    @Override public void validate(TextView textView, String text) {
       /* Validation code here */
    }
});
Christopher Perry
fonte
4
@fremmedehenvendelser: every EditTextIS-ATextView
Niks
2
abstração incrível e uso da classe abstrata
Saher Ahwal
1
@fullmeriffic provavelmente você não inicializou seu EditText. Certifique-se de que você está chamando addTextChangedListenerdepois de resolver o seu EditText do ponto de vista
Ghostli
1
@StephaneEybert É uma classe anônima #
Christopher Perry
2
Princípio de segregação de interface na prática
Maciej Beimcik
92

Se você quiser imagens e pop-ups de validação agradáveis ​​quando ocorrer um erro, poderá usar o setErrormétodo da EditTextclasse conforme descrito aqui

Captura de tela do uso de setError, tirada de Donn Felker, o autor da postagem vinculada

Donn Felker
fonte
Como você obtém um TextWatcher para acessar dois EditTexts? Adicionei com sucesso um TextWatcher ao meu passwordConfirmTextField, mas preciso fazer referência ao outro passwordTextField, para que eu possa compará-lo. Alguma sugestão?
Zonker.in.Geneva 20/04
26

Para reduzir a verbosidade da lógica de validação, criei uma biblioteca para Android . Ele cuida da maioria das validações do dia-a-dia usando Anotações e regras internas. Há restrições, como @TextRule, @NumberRule, @Required, @Regex, @Email, @IpAddress, @Password, etc.,

Você pode adicionar essas anotações às referências do widget da interface do usuário e executar validações. Também permite realizar validações de forma assíncrona, o que é ideal para situações como verificação de nome de usuário exclusivo de um servidor remoto.

Há um exemplo na página inicial do projeto sobre como usar anotações. Você também pode ler a postagem do blog associado, onde escrevi exemplos de códigos sobre como escrever regras personalizadas para validações.

Aqui está um exemplo simples que descreve o uso da 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;

A biblioteca é extensível, você pode escrever suas próprias regras estendendo a Ruleclasse.

Ragunath Jawahar
fonte
Esta biblioteca funciona como um encanto. Mas as anotações @TextRule foram removidas da versão 2.0.3?
LTroya
1
Foi substituído pela @Lengthanotação.
Ragunath Jawahar 08/04/19
@RagunathJawahar Observei que a validação não funciona se você validar os dados recebidos, ou seja, entre em contato, por isso estou tentando validar e-mails provenientes de Intenção -> Contatos, mas assim que me concentrar no EditText e adicionar / excluir qualquer texto, validação funciona como validação também está sendo chamado no TextChange e validate () também é chamado quando recebemos dados do Contato.
Ronak Mehta 25/10
11

Esta foi uma boa solução daqui

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
fonte
como usá-lo junto com o espaço e não limitar dois espaços um ao lado do outro?
chiru
10

Abordagem atualizada - TextInputLayout:

O Google lançou recentemente a biblioteca de suporte ao design e há um componente chamado TextInputLayout e ele suporta a exibição de um erro via setErrorEnabled(boolean)e setError(CharSequence).

Como usá-lo?

Etapa 1: agrupar seu EditText com 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>

Etapa 2: Validar 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);
    }
}

Eu criei um exemplo no meu repositório Github ; faça o checkout do exemplo, se desejar!

Paresh Mayani
fonte
Melhor resposta, mas eu tive que usar com.google.android.material.textfield.TextInputLayout(observe a mudança material ). Entendi com esta resposta: stackoverflow.com/a/56753953/900394
Alaa M.
8

Eu escrevi uma classe que estende o EditText que suporta nativamente alguns métodos de validação e é realmente muito flexível.

Atualmente, como eu escrevo, nativamente suportados por métodos de validação de atributos xml são:

  1. alfa
  2. alfanumérico
  3. numérico
  4. regexp genérico
  5. vazio da corda

Você pode conferir aqui

Espero que goste :)

Andrea Baccega
fonte
7

Acho InputFilter ser mais apropriado para validar entradas de texto no android.

Aqui está um exemplo simples: como uso o InputFilter para limitar caracteres em um EditText no Android?

Você pode adicionar um brinde ao feedback do usuário sobre suas restrições. Verifique também a etiqueta android: inputType.

Moisés
fonte
1
Essa é uma boa solução para itens que podem ser validados enquanto você digita (entrada alfanumérica), mas não funcionaria para itens que só devem ser validados quando o usuário terminar de inserir a entrada (endereço de email).
precisa
Como você desencadeou esse brinde? O filtro impede que qualquer observador de texto reaja ... Talvez com um onKeyListener?
intervalo de
Acionei o Toast com uma condição IF do método filter () (na classe InputFilter).
Moisés
6

Eu precisava fazer a validação dentro do campo e não a validação entre campos para testar se meus valores eram valores de ponto flutuante sem sinal em um caso e valores de ponto flutuante assinados em outro. Aqui está o que parece funcionar para mim:

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

Observe que você não deve ter espaços dentro de "numberSigned | numberDecimal". Por exemplo: "numberSigned | numberDecimal" não funcionará. Não sei por que.

user405821
fonte
5

Isso parece realmente promissor e exatamente o que o documento solicitou para mim:

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

validadores personalizados mais estes incorporados:

  • regexp : para regexp personalizado
  • numérico : para um único campo numérico
  • alfa : para um campo somente alfa
  • alphaNumeric : adivinhem?
  • personName : verifica se o texto digitado é o nome ou sobrenome de uma pessoa.
  • personFullName : verifica se o valor digitado é um nome completo completo.
  • email : verifica se o campo é um email válido
  • creditCard : verifica se o campo contém um cartão de crédito válido usando o algoritmo Luhn
  • phone : verifica se o campo contém um número de telefone válido
  • domainName : verifica se o campo contém um nome de domínio válido (sempre passa no teste no nível da API <8)
  • ipAddress : verifica se o campo contém um endereço IP válido
  • webUrl : verifica se o campo contém um URL válido (sempre passa no teste no nível da API <8)
  • date : verifica se o campo é um formato válido de data / data / hora (se customFormat estiver configurado, verifica com customFormat)
  • nocheck : não verifica nada, exceto o vazio do campo.
Abdômen
fonte
2

No arquivo main.xml

Você pode colocar o seguinte atributo para validar apenas caracteres alfabéticos podem aceitar no edittext.

Faça isso :

  android:entries="abcdefghijklmnopqrstuvwxyz"
KKumar
fonte
2

Você pode obter o comportamento desejado ouvindo quando o usuário pressiona o botão "Concluído" no teclado. Confira também outras dicas sobre como trabalhar com o EditText no meu post "Validação de formulário do Android - o caminho certo"

Código de amostra:

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
fonte
0

para validação de e-mail e senha, tente

  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
fonte
-2

Eu criei esta biblioteca para o Android, onde você pode validar um EditText de design de material dentro e EditTextLayout facilmente assim:

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

então você pode usá-lo assim:

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

Então você pode verificar se é válido assim:

    ageSmartEditText.check()

Para obter mais exemplos e personalização, verifique o repositório https://github.com/TeleClinic/SmartEditText

Karim
fonte