Android: Wie kann ich die EditText-Eingabe überprüfen?

169

Ich muss eine Formulareingabevalidierung für eine Reihe von EditTexts durchführen. Ich verwende OnFocusChangeListeners, um die Validierung auszulösen, nachdem der Benutzer sie eingegeben hat, aber dies verhält sich für den letzten EditText nicht wie gewünscht.

Wenn ich während der Eingabe in den endgültigen EditText auf die Schaltfläche "Fertig" klicke, wird die Eingabemethode getrennt, aber der technische Fokus geht nie auf den EditText verloren (und daher erfolgt keine Validierung).

Was ist die beste Lösung?

Sollte ich überwachen, wann die InputMethod von jedem EditText getrennt wird, anstatt wenn sich der Fokus ändert? Wenn das so ist, wie?

Stefan
quelle
1
Müssen Sie die EditText-Eingabe wirklich gleichzeitig mit der Eingabe durch den Benutzer überprüfen? Warum validieren Sie die EditText-Dateien nicht einfach, sobald der Benutzer auf die Schaltfläche Fertig geklickt hat?
Cristian
Genau das möchte ich: Damit der Text überprüft wird, wenn der Benutzer auf die Schaltfläche "Fertig" klickt (mit "Fertig" meine ich die Schaltfläche "Fertig" im QWERTY InputManager ... NICHT die Schaltfläche "Senden" des Formulars). Wenn ich auf die Schaltfläche Fertig drücke, bleibt der Fokus auf dem letzten Element im Formular und meine Validierungsmethode wird nie ausgelöst. Hoffe mein Wortlaut ist klar ...
Stefan
@Cristians Lösung ist genau das, wonach ich gesucht habe und ist hier zu finden: stackoverflow.com/questions/43013812/…
LampPost
@Cristian Kommt etwas spät, aber ich suche nach einer Lösung, bei der die EditText-Dateien validiert werden, während die Person tippt. Ich habe ein Anmelde- / Registrierungsformular und möchte die Schaltfläche "Senden" nur anzeigen, wenn die Formulardaten gültig sind.
Zonker.in.Geneva

Antworten:

154

Warum benutzt du nicht TextWatcher?

Da Sie eine Reihe von EditTextzu validierenden Feldern haben, denke ich, dass Folgendes zu Ihnen passen wird:

  1. Ihre Aktivität implementiert die android.text.TextWatcherSchnittstelle
  2. Sie fügen Ihren EditText-Feldern TextChanged-Listener hinzu
txt1.addTextChangedListener(this);
txt2.addTextChangedListener(this);
txt3.addTextChangedListener(this);
  1. Von den überschriebenen Methoden können Sie die afterTextChanged(Editable s)Methode wie folgt verwenden
@Override
public void afterTextChanged(Editable s) {
    // validation code goes here
}

Das Editable shilft nicht wirklich herauszufinden, welcher Text des EditText-Felds geändert wird. Sie können aber direkt den Inhalt der EditText-Felder wie überprüfen

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

in der gleichen Methode. Ich hoffe ich bin klar und wenn ich es bin, hilft es! :) :)

EDIT: Für einen saubereren Ansatz beziehen Sie sich auf die Antwort von Christopher Perry unten.

Niks
quelle
3
Das sieht genau so aus, wie ich es brauche. Hatte noch nichts von TextWatcher gehört (neu im SDK / API), aber ich werde es testen und sehen, ob es sich so verhält, wie ich es mir vorstelle. Danke für die Information!
Stefan
1
Bitte! :) Können Sie nach der Validierung mitteilen, wie Sie den Benutzer über den Validierungsfehler informieren werden? Ich suche derzeit nach den besten Methoden dafür.
Niks
Nikhil Patil, ich benutze Toast nur, um den Benutzer wissen zu lassen, dass er etwas falsch gemacht hat. Gibt es einen Grund, warum dies in Ihrem Fall nicht effektiv ist?
Jewgeni Simkin
5
Natürlich ist Toast ein natürlicher Weg auf Android. Aber wenn wir eine beträchtliche Anzahl von Elementen auf dem Bildschirm haben, die validiert werden müssen, scheinen Toasts nicht die richtige Wahl zu sein. (IMHO, es würde den Benutzer ärgern.) Ich habe mit TextView.setError () ( developer.android.com
Niks
1
Obwohl TextWatcher nur unzureichend unterstützt wird, funktioniert es ... irgendwie!
Tivie
125

TextWatcher ist für meinen Geschmack etwas ausführlich, daher habe ich etwas leichter zu schlucken gemacht:

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

Verwenden Sie es einfach so:

editText.addTextChangedListener(new TextValidator(editText) {
    @Override public void validate(TextView textView, String text) {
       /* Validation code here */
    }
});
Christopher Perry
quelle
4
@fremmedehenvendelser: jeder EditTextIS-ATextView
Niks
2
großartige Abstraktion und Verwendung der abstrakten Klasse
Saher Ahwal
1
@fullmeriffic höchstwahrscheinlich haben Sie Ihren EditText nicht initialisiert. addTextChangedListenerStellen Sie sicher, dass Sie anrufen, nachdem Sie Ihren Edittext aus der Ansicht aufgelöst haben
Ghostli
1
@StephaneEybert Es ist eine anonyme Klasse
Christopher Perry
2
Prinzip der Schnittstellentrennung in der Praxis
Maciej Beimcik
92

Wenn Sie bei einem Fehler nette Überprüfungs-Popups und Bilder wünschen, können Sie die hier beschriebene setErrorMethode der EditTextKlasse verwenden

Screenshot der Verwendung von setError von Donn Felker, dem Autor des verlinkten Beitrags

Donn Felker
quelle
Wie kann ein TextWatcher auf zwei EditTexts zugreifen? Ich habe erfolgreich einen TextWatcher zu meinem hinzugefügt passwordConfirmTextField, muss aber auf den anderen verweisen passwordTextField, damit ich sie vergleichen kann. Irgendwelche Vorschläge?
Zonker.in.Geneva
26

Um die Ausführlichkeit der Validierungslogik zu verringern, habe ich eine Bibliothek für Android erstellt . Es kümmert sich um die meisten täglichen Validierungen mithilfe von Anmerkungen und integrierten Regeln. Es gibt Einschränkungen wie @TextRule, @NumberRule, @Required, @Regex, @Email, @IpAddress, @Password, usw.,

Sie können diese Anmerkungen zu Ihren UI-Widget-Referenzen hinzufügen und Überprüfungen durchführen. Außerdem können Sie Validierungen asynchron durchführen. Dies ist ideal für Situationen, in denen beispielsweise von einem Remoteserver nach einem eindeutigen Benutzernamen gesucht wird.

Auf der Projekthomepage finden Sie ein Beispiel für die Verwendung von Anmerkungen. Sie können auch den zugehörigen Blog-Beitrag lesen, in dem ich Beispielcodes zum Schreiben benutzerdefinierter Regeln für Validierungen geschrieben habe.

Hier ist ein einfaches Beispiel, das die Verwendung der Bibliothek zeigt.

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

Die Bibliothek ist erweiterbar. Sie können Ihre eigenen Regeln schreiben, indem Sie die RuleKlasse erweitern.

Ragunath Jawahar
quelle
Diese Bibliothek wirkt wie ein Zauber. Aber die @ TextRule-Annotationen wurden aus Version 2.0.3 entfernt?
LTroya
1
Es wurde durch die @LengthAnmerkung ersetzt.
Ragunath Jawahar
@RagunathJawahar Ich habe festgestellt, dass die Validierung nicht funktioniert, wenn Sie eingehende Daten validieren, z. B. Kontakt. Daher versuche ich, E-Mails zu validieren, die von Intent -> Kontakte stammen. Sobald ich mich jedoch auf EditText konzentriere und Text hinzufüge / lösche, wird die Validierung durchgeführt funktioniert, da die Validierung auch in TextChange aufgerufen wird und validate () auch aufgerufen wird, wenn wir Daten von Contact erhalten.
Ronak Mehta
11

Dies war eine schöne Lösung von hier

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
quelle
Wie verwende ich es zusammen mit dem Leerzeichen und beschränke keine zwei Leerzeichen nebeneinander?
Chiru
10

Aktualisierter Ansatz - TextInputLayout:

Google hat kürzlich eine Design-Support-Bibliothek gestartet. Es gibt eine Komponente namens TextInputLayout , die das Anzeigen eines Fehlers über setErrorEnabled(boolean)und unterstützt setError(CharSequence).

Wie benutzt man es?

Schritt 1: Wickeln Sie Ihren EditText mit TextInputLayout ein:

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

Schritt 2: Überprüfen Sie die Eingabe

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

Ich habe ein Beispiel über mein Github-Repository erstellt . Schauen Sie sich das Beispiel an, wenn Sie möchten!

Paresh Mayani
quelle
Beste Antwort, aber ich musste verwenden com.google.android.material.textfield.TextInputLayout(beachten Sie die Materialänderung ). Ich
Alaa M.
8

Ich habe eine Klasse geschrieben, die EditText erweitert, die nativ einige Validierungsmethoden unterstützt und tatsächlich sehr flexibel ist.

Während ich schreibe, werden aktuelle Methoden zur Validierung von XML-Attributen nativ unterstützt :

  1. Alpha
  2. alphanumerisch
  3. numerisch
  4. generischer regulärer Ausdruck
  5. String Leere

Sie können es hier überprüfen

Hoffe es gefällt euch :)

Andrea Baccega
quelle
7

Ich finde InputFilter besser geeignet, um Texteingaben auf Android zu validieren.

Hier ein einfaches Beispiel: Wie verwende ich InputFilter, um Zeichen in einem EditText in Android einzuschränken?

Sie können einen Toast hinzufügen, um den Benutzer über Ihre Einschränkungen zu informieren. Überprüfen Sie auch das android: inputType-Tag aus.

Moisés
quelle
1
Dies ist eine gute Lösung für Dinge, die während der Eingabe validiert werden können (alphanumerische Eingabe), aber nicht für Dinge, die erst validiert werden sollten, wenn der Benutzer die Eingabe eingegeben hat (E-Mail-Adresse).
Peter Ajtai
Wie würden Sie diesen Toast auslösen? Der Filter verhindert, dass Textwatcher reagieren ... Vielleicht mit einem onKeyListener?
Span
Ich habe diesen Toast mit einer IF-Bedingung aus der filter () -Methode (in der InputFilter-Klasse) ausgelöst.
Moisés
6

Ich musste eine Validierung innerhalb des Feldes und keine Validierung zwischen den Feldern durchführen, um zu testen, ob meine Werte in einem Fall vorzeichenlose Gleitkommawerte und in einem anderen Fall vorzeichenbehaftete Gleitkommawerte waren. Folgendes scheint für mich zu funktionieren:

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

Beachten Sie, dass in "numberSigned | numberDecimal" keine Leerzeichen stehen dürfen. Zum Beispiel: "numberSigned | numberDecimal" funktioniert nicht. Ich bin mir nicht sicher warum.

user405821
quelle
5

Das sieht sehr vielversprechend aus und genau das, was der Arzt für mich bestellt hat:

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

Benutzerdefinierte Validatoren sowie diese integrierten:

  • regulärer Ausdruck : für benutzerdefinierten regulären Ausdruck
  • numerisch : für ein nur numerisches Feld
  • Alpha : Für ein Nur-Alpha-Feld
  • alphaNumeric : weißt du was?
  • personName : Überprüft, ob der eingegebene Text ein Vor- oder Nachname einer Person ist.
  • personFullName : Überprüft, ob der eingegebene Wert ein vollständiger vollständiger Name ist.
  • E-Mail : Überprüft, ob das Feld eine gültige E-Mail ist
  • creditCard : Überprüft mithilfe des Luhn-Algorithmus , ob das Feld eine gültige Kreditkarte enthält
  • Telefon : Überprüft, ob das Feld eine gültige Telefonnummer enthält
  • Domänenname : Überprüft, ob das Feld einen gültigen Domänennamen enthält (besteht den Test immer in API-Stufe <8).
  • ipAddress : Überprüft, ob das Feld eine gültige IP-Adresse enthält
  • webUrl : Überprüft, ob das Feld eine gültige URL enthält (besteht den Test immer in API Level <8).
  • Datum : Überprüft, ob das Feld ein gültiges Datums- / Datums- / Uhrzeitformat hat (wenn customFormat festgelegt ist, wird dies mit customFormat überprüft.)
  • nocheck : Es prüft nichts außer der Leere des Feldes.
Abs
quelle
2

In der Datei main.xml

Sie können den folgenden Attribut setzen, um zu überprüfen, ob nur alphabetische Zeichen in edittext akzeptiert werden können.

Mach das :

  android:entries="abcdefghijklmnopqrstuvwxyz"
KKumar
quelle
2

Sie können das gewünschte Verhalten erzielen, indem Sie zuhören, wenn der Benutzer auf der Tastatur auf die Schaltfläche "Fertig" klickt. Weitere Tipps zur Arbeit mit EditText finden Sie in meinem Beitrag "Android-Formularüberprüfung - der richtige Weg".

Beispielcode:

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

Versuchen Sie es mit einer E-Mail- und Passwortüberprüfung

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

Ich habe diese Bibliothek für Android erstellt, in der Sie ein Materialdesign EditText im Inneren und EditTextLayout einfach so überprüfen können:

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

dann können Sie es so verwenden:

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

Dann können Sie überprüfen, ob es so gültig ist:

    ageSmartEditText.check()

Weitere Beispiele und Anpassungen finden Sie im Repository unter https://github.com/TeleClinic/SmartEditText

Karim
quelle