Android: Jak mogę sprawdzić poprawność danych wejściowych EditText?


169

Muszę sprawdzić poprawność danych wejściowych formularza w serii EditTexts. Używam OnFocusChangeListeners do wyzwalania walidacji po wpisaniu przez użytkownika do każdego z nich, ale to nie zachowuje się zgodnie z oczekiwaniami dla ostatniego EditText.

Jeśli kliknę przycisk „Gotowe” podczas wpisywania końcowego tekstu edycji, wówczas metoda InputMethod zostanie odłączona, ale technicznie rzecz biorąc, fokus nigdy nie zostanie utracony na EditText (a więc nigdy nie nastąpi walidacja).

Jakie jest najlepsze rozwiązanie?

Czy powinienem monitorować, kiedy InputMethod odłącza się od każdego EditText, a nie kiedy zmienia się fokus? Jeśli tak to jak?


1
Czy naprawdę musisz sprawdzać poprawność danych wejściowych EditText w tym samym czasie, gdy użytkownik pisze? Dlaczego po prostu nie sprawdzisz poprawności EditText, gdy użytkownik kliknie przycisk Gotowe?
Cristian

Dokładnie tego chcę: aby tekst był weryfikowany, gdy użytkownik kliknie przycisk Gotowe (przez przycisk Gotowe mam na myśli przycisk „Gotowe” w module QWERTY InputManager ... a nie przycisk przesyłania formularza). Tyle że po naciśnięciu przycisku Gotowe fokus pozostaje na ostatnim elemencie formularza, a moja metoda walidacji nigdy nie jest wyzwalana. Mam nadzieję, że moje sformułowanie jest jasne ...
Stefan

Rozwiązanie @Cristian jest dokładnie tym, czego szukałem i znajduje się tutaj: stackoverflow.com/questions/43013812/…
LampPost

@Cristian Spóźniam się trochę, ale szukam rozwiązania, w którym EditText są sprawdzane, gdy osoba pisze. Mam formularz logowania / rejestracji i chcę wyświetlać przycisk „Prześlij” tylko wtedy, gdy dane formularza są prawidłowe.
Zonker.in.Geneva

Odpowiedzi:


154

Dlaczego nie używasz TextWatcher?

Ponieważ masz kilka EditTextpudełek do walidacji, myślę, że będą Ci odpowiadać:

  1. Twoja aktywność implementuje android.text.TextWatcherinterfejs
  2. Dodajesz detektory TextChanged do pól EditText
txt1.addTextChangedListener(this);
txt2.addTextChangedListener(this);
txt3.addTextChangedListener(this);
  1. Spośród zastąpionych metod można użyć afterTextChanged(Editable s)metody w następujący sposób
@Override
public void afterTextChanged(Editable s) {
    // validation code goes here
}

To Editable snaprawdę nie pomaga w znalezieniu tekstu pola edycji tekstu, który jest zmieniany. Ale możesz bezpośrednio sprawdzić zawartość pól EditText, takich jak

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

w ten sam sposób. Mam nadzieję, że wszystko jest jasne, a jeśli tak, to pomaga! :)

EDYCJA: Aby uzyskać czystsze podejście, zapoznaj się z odpowiedzią Christophera Perry'ego poniżej.


3
To wygląda dokładnie na to, czego potrzebuję. Nie słyszałem o TextWatcherze (nowości w SDK / API), ale przetestuję go i zobaczę, czy zachowuje się tak, jak myślę, że będzie. Dzięki za informację!
Stefan

1
nie ma za co! :) Teraz, gdy ją weryfikujesz, czy możesz podzielić się, w jaki sposób zamierzasz poinformować użytkownika o niepowodzeniu weryfikacji? Obecnie szukam najlepszych metod na to samo.
Niks

Nikhil Patil, po prostu używam Toast, aby poinformować użytkownika, że ​​zrobił coś złego. Czy jest jakiś powód, dla którego to nie będzie skuteczne w Twoim przypadku?
Jewgienij Simkin

5
Oczywiście Toast jest naturalnym sposobem na Androida. Ale kiedy mamy na ekranie znaczną liczbę elementów, które wymagają weryfikacji, toasty nie wydają się być właściwym wyborem. (IMHO, denerwowałoby użytkownika) Eksperymentowałem z TextView.setError () ( developer.android.com / reference / android / widget /…
Niks

1
Chociaż TextWatcher ma słabe wsparcie, działa ... trochę!
Tivie,

125

TextWatcher jest trochę rozwlekły jak na mój gust, więc ułatwiłem coś do przełknięcia:

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

Po prostu użyj tego w ten sposób:

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

4
@fremmedehenvendelser: każdy EditTextIS-ATextView
Niks

2
niesamowita abstrakcja i wykorzystanie klasy abstrakcyjnej
Saher Ahwal

1
@fullmeriffic najprawdopodobniej nie zainicjowałeś swojego EditText. Upewnij się, że dzwonisz addTextChangedListenerpo rozwiązaniu pliku edittext z widoku
Ghostli

1
@StephaneEybert To anonimowe zajęcia
Christopher Perry

2
Zasada segregacji interfejsów w praktyce
Maciej Beimcik

92

Jeśli chcesz mieć ładne wyskakujące okienka walidacji i obrazy, gdy wystąpi błąd, możesz użyć setErrormetody EditTextklasy, jak tutaj opisuję

Zrzut ekranu przedstawiający użycie setError autorstwa Donna Felkera, autora posta, do którego prowadzi link


Jak uzyskać TextWatchera, aby uzyskać dostęp do dwóch EditTextów? Pomyślnie dodałem TextWatchera do mojego passwordConfirmTextField, ale muszę odwołać się do drugiego passwordTextField, aby móc je porównać. Jakieś sugestie?
Zonker.in.Geneva

26

W celu zmniejszenia szczegółowości logiki walidacji stworzyłem bibliotekę dla Androida . Zajmuje się większością codziennych walidacji za pomocą adnotacji i wbudowanych reguł. Istnieją ograniczenia, takie jak @TextRule, @NumberRule, @Required, @Regex, @Email, @IpAddress, @Password, itd.,

Możesz dodać te adnotacje do odniesień do widżetów interfejsu użytkownika i przeprowadzać weryfikacje. Pozwala również na wykonywanie walidacji asynchronicznie, co jest idealne w sytuacjach, takich jak sprawdzanie unikalnej nazwy użytkownika ze zdalnego serwera.

Na stronie głównej projektu znajduje się przykład użycia adnotacji. Możesz również przeczytać powiązany post na blogu, w którym napisałem przykładowe kody dotyczące pisania niestandardowych reguł walidacji.

Oto prosty przykład ilustrujący użycie biblioteki.

@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;

Biblioteka jest rozszerzalna, możesz pisać własne reguły rozszerzając Ruleklasę.


Ta biblioteka działa jak urok. Ale adnotacje @TextRule zostały usunięte z wersji 2.0.3?
LTroya

1
Został zastąpiony @Lengthadnotacją.
Ragunath Jawahar

@RagunathJawahar Zauważyłem, że walidacja nie działa, jeśli weryfikujesz przychodzące dane, tj. Kontakt, więc próbuję sprawdzić poprawność adresu e-mail, który pochodzi z Intent -> Kontakty, ale kiedy skupiam się na EditText i dodam / usunę dowolny tekst, a następnie zweryfikuję działa, ponieważ funkcja validation jest również wywoływana w TextChange, a validate () jest również wywoływane, gdy otrzymujemy dane od Contact.
Ronak Mehta,

11

To było miłe rozwiązanie z tutaj

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

jak używać go razem z przestrzenią i nie ograniczać dwóch miejsc obok siebie?
chiru

10

Zaktualizowane podejście - TextInputLayout:

Firma Google niedawno uruchomiła bibliotekę obsługi projektowania i jest jeden komponent o nazwie TextInputLayout, który obsługuje wyświetlanie błędów za pośrednictwem setErrorEnabled(boolean)i setError(CharSequence).

Jak tego użyć?

Krok 1: Zawiń swój EditText za pomocą 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>

Krok 2: Sprawdź poprawność danych wejściowych

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

Utworzyłem przykład w moim repozytorium Github , sprawdź przykład, jeśli chcesz!


Najlepsza odpowiedź, ale musiałem użyć com.google.android.material.textfield.TextInputLayout(zauważ istotną zmianę). Rozumiem z tej odpowiedzi: stackoverflow.com/a/56753953/900394
Alaa M.

8

Napisałem klasę, która rozszerza EditText, która natywnie obsługuje niektóre metody walidacji i jest w rzeczywistości bardzo elastyczna.

Obecne, jak piszę, natywnie obsługiwane przez metody walidacji atrybutów xml to:

  1. alfa
  2. alfanumeryczne
  3. numeryczny
  4. ogólne wyrażenie regularne
  5. pustość łańcucha

Możesz to sprawdzić tutaj

Mam nadzieję, że Ci się spodoba :)


7

Uważam, że InputFilter jest bardziej odpowiedni do sprawdzania poprawności danych wejściowych w systemie Android.

Oto prosty przykład: Jak za pomocą InputFilter ograniczyć liczbę znaków w EditText w systemie Android?

Możesz dodać Toast, aby przekazać użytkownikowi opinię o swoich ograniczeniach. Sprawdź również tag android: inputType.


1
Jest to dobre rozwiązanie dla rzeczy, które można sprawdzić podczas wpisywania (wprowadzanie alfanumeryczne), ale nie będzie działać w przypadku rzeczy, które powinny być sprawdzane dopiero po zakończeniu wprowadzania danych przez użytkownika (adres e-mail).
Peter Ajtai

Jak uruchomiłbyś ten Toast? Filtr zapobiega reakcjom jakichkolwiek wiadomości tekstowych ... Być może za pomocą onKeyListener?
obejmuje

Uruchomiłem to Toast z warunkiem IF z metody filter () (w klasie InputFilter).
Moisés

6

Musiałem przeprowadzić walidację wewnątrz pola, a nie walidację między polami, aby sprawdzić, czy moje wartości były wartościami zmiennoprzecinkowymi bez znaku w jednym przypadku, a podpisanymi wartościami zmiennoprzecinkowymi w innym. Oto, co wydaje mi się działać:

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

Zauważ, że nie możesz mieć spacji wewnątrz "numberSigned | numberDecimal". Na przykład: „numberSigned | numberDecimal” nie zadziała. Nie wiem dlaczego.


5

Wygląda to naprawdę obiecująco i dokładnie to, co zamówił dla mnie lekarz:

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

niestandardowe walidatory plus te wbudowane:

  • regexp : dla niestandardowego wyrażenia regularnego
  • numeryczne : dla jedynego pola numerycznego
  • alpha : dla pola tylko alfa
  • alphaNumeric : zgadnij co?
  • personName : sprawdza, czy wprowadzony tekst to imię czy nazwisko osoby.
  • personFullName : sprawdza, czy wprowadzona wartość jest pełną nazwą.
  • email : sprawdza, czy pole jest prawidłowym adresem e-mail
  • karta kredytowa : sprawdza, czy w polu znajduje się ważna karta kredytowa przy użyciu algorytmu Luhn
  • telefon : sprawdza, czy pole zawiera prawidłowy numer telefonu
  • domainName : sprawdza, czy pole zawiera prawidłową nazwę domeny (zawsze przechodzi test na poziomie API <8)
  • ipAddress : sprawdza, czy pole zawiera prawidłowy adres IP
  • webUrl : sprawdza, czy pole zawiera prawidłowy adres URL (zawsze przechodzi test na poziomie API <8)
  • data : sprawdza, czy pole ma prawidłowy format daty / godziny (jeśli ustawiony jest format customFormat, sprawdza za pomocą customFormat)
  • nocheck : Nie sprawdza niczego poza pustością pola.

2

W pliku main.xml

Możesz umieścić następujący atrybut, aby sprawdzić poprawność tylko znaków alfabetu, które można zaakceptować w edytorze.

Zrób to :

  android:entries="abcdefghijklmnopqrstuvwxyz"

2

Możesz uzyskać pożądane zachowanie, słuchając, gdy użytkownik naciska przycisk „Gotowe” na klawiaturze, a także inne wskazówki dotyczące pracy z EditText w moim poście „Sprawdzanie poprawności formularzy Androida - właściwy sposób”

Przykładowy kod:

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

do weryfikacji adresu e-mail i hasła

  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

Utworzyłem tę bibliotekę dla Androida, w której możesz łatwo sprawdzić poprawność projektu materiału EditText wewnątrz i EditTextLayout w następujący sposób:

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

możesz go użyć w ten sposób:

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

Następnie możesz sprawdzić, czy jest ważny w następujący sposób:

    ageSmartEditText.check()

Aby uzyskać więcej przykładów i dostosowań, sprawdź repozytorium https://github.com/TeleClinic/SmartEditText

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.