Android: Bagaimana saya bisa memvalidasi input EditText?

169

Saya perlu melakukan validasi input formulir pada serangkaian EditText. Saya menggunakan OnFocusChangeListeners untuk memicu validasi setelah pengguna mengetik masing-masing, tetapi ini tidak berperilaku seperti yang diinginkan untuk EditText terakhir.

Jika saya mengklik tombol "Selesai" saat mengetik di EditText akhir maka InputMethod terputus, tetapi secara teknis fokus tidak pernah hilang pada EditText (dan validasi tidak pernah terjadi).

Apa solusi terbaik?

Haruskah saya memantau ketika InputMethod melepaskan ikatan dari setiap EditText daripada ketika fokus berubah? Jika ya, bagaimana caranya?

Stefan
sumber
1
Apakah Anda benar-benar perlu memvalidasi input EditText pada saat yang sama saat pengguna mengetik? Mengapa Anda tidak memvalidasi EditText begitu pengguna mengklik tombol Done?
Cristian
Itulah yang saya inginkan: teks diverifikasi ketika pengguna mengklik tombol Selesai (dengan tombol Selesai maksud saya tombol "Selesai" pada QWERTY InputManager ... BUKAN tombol kirim formulir). Kecuali ketika saya menekan tombol Selesai, fokus tetap pada elemen terakhir dalam formulir, dan metode validasi saya tidak pernah terpicu. Semoga kata-kata saya jelas ...
Stefan
Solusi
@Cristian
@Cristian Datang agak terlambat, tapi saya sedang mencari solusi di mana EditText divalidasi saat orang tersebut mengetik. Saya memiliki formulir Login / Daftar dan saya ingin menunjukkan tombol "Kirim" hanya ketika data formulir valid.
Zonker.in.Geneva

Jawaban:

154

Kenapa tidak kamu gunakan TextWatcher?

Karena Anda memiliki sejumlah EditTextkotak untuk divalidasi, saya pikir yang berikut ini cocok untuk Anda:

  1. Aktivitas Anda mengimplementasikan android.text.TextWatcherantarmuka
  2. Anda menambahkan pendengar TextChanged ke kotak EditText Anda
txt1.addTextChangedListener(this);
txt2.addTextChangedListener(this);
txt3.addTextChangedListener(this);
  1. Dari metode yang diganti, Anda dapat menggunakan afterTextChanged(Editable s)metode ini sebagai berikut
@Override
public void afterTextChanged(Editable s) {
    // validation code goes here
}

Tidak Editable sterlalu membantu menemukan teks kotak EditText mana yang sedang diubah. Tapi Anda bisa langsung mengecek isi kotak EditText suka

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

dalam metode yang sama. Saya harap saya jelas dan jika saya, itu membantu! :)

EDIT: Untuk pendekatan yang lebih bersih lihat jawaban Christopher Perry di bawah ini.

Niks
sumber
3
Itu persis seperti yang saya butuhkan. Belum pernah mendengar tentang TextWatcher (baru di SDK / API), tapi saya akan mengujinya dan melihat apakah berperilaku seperti yang saya pikir akan terjadi. Terimakasih atas infonya!
Stefan
1
sama-sama! :) sekarang setelah Anda memvalidasinya, dapatkah Anda membagikan bagaimana Anda akan memberi tahu pengguna tentang kegagalan validasi? Saat ini saya sedang mencari metode terbaik untuk hal yang sama.
Niks
Nikhil Patil, saya hanya menggunakan Toast untuk memberi tahu pengguna bahwa mereka telah melakukan kesalahan. Apakah ada alasan mengapa itu tidak efektif dalam kasus Anda?
Yevgeny Simkin
5
Tentu saja, Toast adalah cara alami di android. Tetapi ketika kita memiliki sejumlah besar elemen di layar yang memerlukan validasi, toasts sepertinya bukan pilihan yang tepat. (IMHO, Ini akan mengganggu pengguna) Saya telah bereksperimen dengan TextView.setError () ( developer.android.com / referensi / android / widget / ...
Niks
1
Meskipun ada dukungan yang buruk pada TextWatcher, itu berfungsi ... agak!
Tivie
126

TextWatcher agak verbose untuk seleraku, jadi aku membuat sesuatu yang sedikit lebih mudah untuk ditelan:

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

Gunakan saja seperti ini:

editText.addTextChangedListener(new TextValidator(editText) {
    @Override public void validate(TextView textView, String text) {
       /* Validation code here */
    }
});
Christopher Perry
sumber
4
@fremmedehenvendelser: setiap EditTextIS-ATextView
Niks
2
abstraksi yang luar biasa dan penggunaan kelas abstrak
Saher Ahwal
1
@fullmeriffic kemungkinan besar Anda tidak menginisialisasi EditText Anda. Pastikan Anda menelepon addTextChangedListenersetelah menyelesaikan edittext dari tampilan
Ghostli
1
@StephaneEybert Ini kelas anonim
Christopher Perry
2
Prinsip pemisahan antarmuka dalam praktik
Maciej Beimcik
92

Jika Anda ingin munculan validasi dan gambar ketika kesalahan terjadi, Anda dapat menggunakan setErrormetode EditTextkelas seperti yang saya jelaskan di sini

Cuplikan layar penggunaan setError diambil dari Donn Felker, penulis posting tertaut

Donn Felker
sumber
Bagaimana Anda mendapatkan TextWatcher untuk mengakses dua EditTexts? Saya telah berhasil menambahkan TextWatcher ke saya passwordConfirmTextField, tetapi saya perlu referensi yang lain passwordTextField, sehingga saya bisa membandingkannya. Ada saran?
Zonker.in.Geneva
26

Untuk mengurangi verbositas logika validasi, saya telah membuat pustaka untuk Android . Sebagian besar hari menangani validasi menggunakan Anotasi dan aturan bawaan. Ada kendala seperti @TextRule, @NumberRule, @Required, @Regex, @Email, @IpAddress, @Password, dll,

Anda dapat menambahkan anotasi ini ke referensi widget UI Anda dan melakukan validasi. Ini juga memungkinkan Anda untuk melakukan validasi secara tidak sinkron yang ideal untuk situasi seperti memeriksa nama pengguna unik dari server jauh.

Ada contoh di halaman utama proyek tentang cara menggunakan anotasi. Anda juga dapat membaca posting blog terkait di mana saya telah menulis kode sampel tentang cara menulis aturan khusus untuk validasi.

Berikut adalah contoh sederhana yang menggambarkan penggunaan perpustakaan.

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

Perpustakaan dapat diperpanjang, Anda dapat menulis aturan Anda sendiri dengan memperluas Rulekelas.

Ragunath Jawahar
sumber
Perpustakaan ini berfungsi seperti pesona. Tapi penjelasan @TextRule telah dihapus dari versi 2.0.3?
LTroya
1
Itu telah diganti dengan @Lengthanotasi.
Ragunath Jawahar
@RagunathJawahar Saya telah mencatat bahwa validasi tidak berfungsi jika Anda memvalidasi data yang masuk, yaitu kontak, jadi saya mencoba untuk memvalidasi Email yang berasal dari Intent -> Kontak, tetapi begitu saya fokus pada EditText dan menambahkan / menghapus teks apa pun kemudian validasi berfungsi karena validasi juga dipanggil di TextChange dan validate () juga dipanggil saat kami menerima data dari Kontak.
Ronak Mehta
11

Ini solusi yang bagus dari sini

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
sumber
bagaimana cara menggunakannya bersama dengan ruang dan membatasi tidak ada dua ruang di samping satu sama lain?
chiru
10

Pendekatan yang diperbarui - TextInputLayout:

Google baru-baru ini meluncurkan perpustakaan dukungan desain dan ada satu komponen bernama TextInputLayout dan itu mendukung menunjukkan kesalahan melalui setErrorEnabled(boolean)dan setError(CharSequence).

Bagaimana cara menggunakannya?

Langkah 1: Bungkus EditText Anda dengan 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>

Langkah 2: Validasi 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);
    }
}

Saya telah membuat contoh dari repositori Github saya , checkout contoh jika Anda mau!

Paresh Mayani
sumber
Jawaban terbaik, tetapi saya harus menggunakan com.google.android.material.textfield.TextInputLayout(perhatikan perubahan materi ). Dapatkan dari jawaban ini: stackoverflow.com/a/56753953/900394
Alaa M.
8

Saya menulis sebuah kelas yang memperluas EditText yang mendukung secara asli beberapa metode validasi dan sebenarnya sangat fleksibel.

Saat ini, ketika saya menulis, secara native didukung melalui metode validasi atribut xml adalah:

  1. alfa
  2. alfa numerik
  3. numerik
  4. regexp generik
  5. kekosongan tali

Anda dapat memeriksanya di sini

Berharap kamu menikmatinya :)

Andrea Baccega
sumber
7

Saya menemukan InputFilter lebih sesuai untuk memvalidasi input teks di android.

Berikut ini contoh sederhana: Bagaimana cara saya menggunakan InputFilter untuk membatasi karakter dalam EditText di Android?

Anda bisa menambahkan Toast untuk memberi umpan balik kepada pengguna tentang batasan Anda. Juga periksa tag android: inputType.

Moisés
sumber
1
Ini adalah solusi yang bagus untuk hal-hal yang dapat divalidasi saat Anda mengetik (input numerik alfa), tetapi itu tidak akan berfungsi untuk hal-hal yang seharusnya hanya divalidasi setelah pengguna selesai memasukkan input (alamat email).
Peter Ajtai
Bagaimana Anda memicu Toast itu? Filter mencegah setiap pengamat teks bereaksi ... Mungkin dengan onKeyListener?
span
Saya memicu Toast dengan kondisi IF dari metode filter () (di kelas InputFilter).
Moisés
6

Saya perlu melakukan validasi intra-bidang dan bukan validasi antar-bidang untuk menguji bahwa nilai saya adalah nilai floating point yang tidak ditandatangani dalam satu kasus dan menandatangani nilai floating point pada kasus lain. Inilah yang tampaknya bekerja untuk saya:

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

Catatan, Anda tidak boleh memiliki spasi di dalam "numberSigned | numberDecimal". Misalnya: "numberSigned | numberDecimal" tidak akan berfungsi. Saya tidak yakin mengapa.

pengguna405821
sumber
5

Ini terlihat sangat menjanjikan dan hanya apa yang diperintahkan oleh dokter untuk saya:

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

validator khusus plus ini bawaan:

  • regexp : untuk regexp kustom
  • numerik : untuk bidang numerik saja
  • alpha : untuk bidang hanya alfa
  • alphaNumeric : coba tebak?
  • personName : memeriksa apakah teks yang dimasukkan adalah nama depan atau belakang seseorang.
  • personFullName : memeriksa apakah nilai yang dimasukkan adalah nama lengkap lengkap.
  • email : memeriksa bahwa bidang tersebut adalah email yang valid
  • creditCard : memeriksa bidang yang berisi kartu kredit yang valid menggunakan Algoritma Luhn
  • telepon : memeriksa bahwa bidang tersebut berisi nomor telepon yang valid
  • domainName : memeriksa bidang yang berisi nama domain yang valid (selalu lulus tes di Tingkat API <8)
  • ipAddress : memeriksa apakah bidang tersebut berisi alamat ip yang valid
  • webUrl : memeriksa apakah bidang tersebut berisi url yang valid (selalu lulus tes di Tingkat API <8)
  • date : memeriksa bahwa bidang adalah format tanggal / datetime yang valid (jika customFormat diatur, periksa dengan customFormat)
  • nocheck : Itu tidak memeriksa apa pun kecuali kekosongan bidang.
Abs
sumber
2

Dalam file main.xml

Anda dapat menempatkan attrubute berikut untuk memvalidasi yang hanya dapat diterima oleh karakter alfabet di edittext.

Melakukan hal ini :

  android:entries="abcdefghijklmnopqrstuvwxyz"
KKumar
sumber
2

Anda bisa mendapatkan perilaku yang diinginkan dengan mendengarkan ketika pengguna menekan tombol "Selesai" pada keyboard, juga memeriksa tips lain tentang bekerja dengan EditText di posting saya "validasi formulir Android - cara yang benar"

Kode sampel:

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

untuk mencoba validasi email dan kata sandi

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

Saya telah membuat perpustakaan ini untuk android di mana Anda dapat memvalidasi desain materi di dalam EditText dan EditTextLayout dengan mudah seperti ini:

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

maka Anda dapat menggunakannya seperti ini:

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

Kemudian Anda dapat memeriksa apakah valid seperti ini:

    ageSmartEditText.check()

Untuk lebih banyak contoh dan penyesuaian periksa repositori https://github.com/TeleClinic/SmartEditText

Karim
sumber