android di Text Change Listener

265

Saya punya situasi, di mana ada dua bidang. field1dan field2. Yang ingin saya lakukan adalah kosong field2ketika field1diubah dan sebaliknya. Jadi pada akhirnya hanya satu bidang yang memiliki konten di dalamnya.

field1 = (EditText)findViewById(R.id.field1);
field2 = (EditText)findViewById(R.id.field2);

field1.addTextChangedListener(new TextWatcher() {

   public void afterTextChanged(Editable s) {}

   public void beforeTextChanged(CharSequence s, int start,
     int count, int after) {
   }

   public void onTextChanged(CharSequence s, int start,
     int before, int count) {
      field2.setText("");
   }
  });

field2.addTextChangedListener(new TextWatcher() {

   public void afterTextChanged(Editable s) {}

   public void beforeTextChanged(CharSequence s, int start,
     int count, int after) {
   }

   public void onTextChanged(CharSequence s, int start,
     int before, int count) {
     field1.setText("");
   }
  });

Ia bekerja baik jika saya melampirkan addTextChangedListenerke field1saja, tetapi ketika saya melakukannya untuk kedua bidang aplikasi crash. Jelas karena mereka mencoba mengubah satu sama lain tanpa batas. Setelah field1perubahan itu dihapus field2pada saat field2ini diubah sehingga akan jelas field1dan seterusnya ...

Adakah yang bisa menyarankan solusi?

inrob
sumber
untuk pengguna baru, gunakan pengikatan data dua arah menggunakan bidang string yang dapat diamati, karena semua solusi yang disediakan di sini dapat menghasilkan starting waiting blocking gc allocjenis kesalahan ini, yang bahkan dapat menyebabkan crash dan hang .. jadi lanjutkan untuk pengikatan data, itu aman dan direkomendasikan oleh google sekarang ..
Maifee Ul Asad

Jawaban:

460

Anda bisa menambahkan tanda centang hanya untuk menghapus ketika teks di bidang tidak kosong (yaitu ketika panjangnya berbeda dari 0).

field1.addTextChangedListener(new TextWatcher() {

   @Override
   public void afterTextChanged(Editable s) {}

   @Override    
   public void beforeTextChanged(CharSequence s, int start,
     int count, int after) {
   }

   @Override    
   public void onTextChanged(CharSequence s, int start,
     int before, int count) {
      if(s.length() != 0)
        field2.setText("");
   }
  });

field2.addTextChangedListener(new TextWatcher() {

   @Override
   public void afterTextChanged(Editable s) {}

   @Override
   public void beforeTextChanged(CharSequence s, int start,
     int count, int after) {
   }

   @Override
   public void onTextChanged(CharSequence s, int start,
     int before, int count) {
      if(s.length() != 0)
         field1.setText("");
   }
  });

Dokumentasi untuk di TextWatcher sini .

Harap juga hormati konvensi penamaan .

pengguna2336315
sumber
1
cara mendeteksi setelah semua bidang berubah, karena, mendeteksi setiap kali itu berubah, ketika tombol apa pun ditekan.
Rafael Guimarães
20

Saya tahu ini sudah tua tetapi seseorang mungkin menemukan ini lagi suatu hari nanti.

Saya memiliki masalah serupa di mana saya akan memanggil setText pada EditText dan onTextChanged akan dipanggil ketika saya tidak menginginkannya. Solusi pertama saya adalah menulis beberapa kode setelah memanggil setText () untuk membatalkan kerusakan yang dilakukan oleh pendengar. Tapi itu tidak terlalu elegan. Setelah melakukan beberapa penelitian dan pengujian saya menemukan bahwa menggunakan getText (). Clear () menghapus teks dengan cara yang sama seperti setText (""), tetapi karena tidak mengatur teks, pendengar tidak dipanggil, sehingga memecahkan masalah saya. Saya mengalihkan semua panggilan setText ("") saya ke getText (). Clear () dan saya tidak membutuhkan perban lagi, jadi mungkin itu akan menyelesaikan masalah Anda juga.

Coba ini:

Field1 = (EditText)findViewById(R.id.field1);
Field2 = (EditText)findViewById(R.id.field2);

Field1.addTextChangedListener(new TextWatcher() {

   public void afterTextChanged(Editable s) {}

   public void beforeTextChanged(CharSequence s, int start,
     int count, int after) {
   }

   public void onTextChanged(CharSequence s, int start,
     int before, int count) {
      Field2.getText().clear();
   }
  });

Field2.addTextChangedListener(new TextWatcher() {

   public void afterTextChanged(Editable s) {}

   public void beforeTextChanged(CharSequence s, int start,
     int count, int after) {
   }

   public void onTextChanged(CharSequence s, int start,
     int before, int count) {
     Field1.getText().clear();
   }
  });
RTHarston
sumber
11

Jika Anda menggunakan Kotlin untuk pengembangan Android maka Anda dapat menambahkan TextChangedListener()menggunakan kode ini:

myTextField.addTextChangedListener(object : TextWatcher{
        override fun afterTextChanged(s: Editable?) {}

        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
    })
iHulk
sumber
5

Agak terlambat dari jawaban, tetapi di sini ada solusi yang dapat digunakan kembali:

/**
 * An extension of TextWatcher which stops further callbacks being called as 
 * a result of a change happening within the callbacks themselves.
 */
public abstract class EditableTextWatcher implements TextWatcher {

    private boolean editing;

    @Override
    public final void beforeTextChanged(CharSequence s, int start, 
                                                    int count, int after) {
        if (editing)
            return;

        editing = true;
        try {
            beforeTextChange(s, start, count, after);
        } finally {
            editing = false;
        }
    }

    protected abstract void beforeTextChange(CharSequence s, int start, 
                                                     int count, int after);

    @Override
    public final void onTextChanged(CharSequence s, int start, 
                                                int before, int count) {
        if (editing)
            return;

        editing = true;
        try {
            onTextChange(s, start, before, count);
        } finally {
            editing = false;
        }
    }

    protected abstract void onTextChange(CharSequence s, int start, 
                                            int before, int count);

    @Override
    public final void afterTextChanged(Editable s) {
        if (editing)
            return;

        editing = true;
        try {
            afterTextChange(s);
        } finally {
            editing = false;
        }
    }

    public boolean isEditing() {
        return editing;
    }

    protected abstract void afterTextChange(Editable s);
}

Jadi ketika hal di atas digunakan, setText()panggilan apa pun yang terjadi di dalam TextWatcher tidak akan mengakibatkan TextWatcher dipanggil lagi:

/**
 * A setText() call in any of the callbacks below will not result in TextWatcher being 
 * called again.
 */
public class MyTextWatcher extends EditableTextWatcher {

    @Override
    protected void beforeTextChange(CharSequence s, int start, int count, int after) {
    }

    @Override
    protected void onTextChange(CharSequence s, int start, int before, int count) {
    }

    @Override
    protected void afterTextChange(Editable s) {
    }
}
Eurig Jones
sumber
5

Saya juga menghadapi masalah yang sama dan terus mendapatkan stackOverflowpengecualian, dan saya datang dengan solusi berikut.

edt_amnt_sent.addTextChangedListener(new TextWatcher() {    
    @Override
    public void afterTextChanged(Editable s) {
        if (skipOnChange)
            return;

        skipOnChange = true;
        try {
            //method
        } catch (NumberFormatException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            skipOnChange = false;
        }
    }
});

edt_amnt_receive.addTextChangedListener(new TextWatcher() {

    @Override
    public void afterTextChanged(Editable s) {

        if (skipOnChange)
            return;

        skipOnChange = true;
        try {
            //method
        } catch (NumberFormatException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            skipOnChange = false;
        }
    }
});

dideklarasikan awalnya boolean skipOnChange = false;

Sumit
sumber
1
"tumpukan penuh" Saya pikir maksud Anda Stack Overflow;)
A Droid
4

Anda juga dapat menggunakan metode hasFocus ():

public void onTextChanged(CharSequence s, int start,
     int before, int count) {
     if (Field2.hasfocus()){
         Field1.setText("");
     }
   }

Menguji ini untuk tugas kuliah yang sedang saya kerjakan untuk mengubah skala suhu saat pengguna mengetiknya. Bekerja dengan sempurna, dan itu jauh lebih sederhana.

renam
sumber
1
Bagaimana dengan editText.setText ketika pengguna memasukkannya? EditText memiliki fokus dalam hal ini
Evgenii Vorobei
solusi terbaik .
Syed Hissaan
3

periksa String sebelum mengeset yang lain EditTextmenjadi kosong. jika Field1kosong maka mengapa perlu diubah lagi ke ("")? sehingga Anda dapat memeriksa ukuran String Anda dengan s.lenght () atau solusi lain

Cara lain yang dapat Anda periksa panjang String adalah:

String sUsername = Field1.getText().toString();
if (!sUsername.matches(""))
{
// do your job
}
Shayan Pourvatan
sumber
2

Saya menulis ekstensi saya sendiri untuk ini, sangat membantu bagi saya. (Kotlin)

Anda hanya dapat menulis seperti itu:

editText.customAfterTextChanged { editable -> 
    //You have accessed the editable object. 
}

Ekstensi saya:

fun EditText.customAfterTextChanged(action: (Editable?)-> Unit){
    this.addTextChangedListener(object : TextWatcher {
       override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
       override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
       override fun afterTextChanged(editable: Editable?) {
        action(editable)
    }
})}
Burak Dizlek
sumber
2
editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }
            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                if (noteid != -1) {
                    MainActivity.notes.set(noteid, String.valueOf(charSequence));
                    MainActivity.arrayAdapter.notifyDataSetChanged();
                }
            }
            @Override
            public void afterTextChanged(Editable editable) {

            }
        });

dalam kode ini noteid pada dasarnya adalah argumen yang diambil kembali yang dimasukkan ke dalam indent atau melewati indent.

  Intent intent = getIntent();
         noteid = intent.getIntExtra("noteid", -1);

kode pada sisi negatifnya pada dasarnya adalah kode tambahan, jika Anda ingin memahami lebih jelas.

how to make the menu or insert the menu in our code , 
    create the  menu folder this the folder created by going into the raw
    ->rightclick->
    directory->name the folder as you wish->
    then click on the directory formed->
    then click on new file and then name for file as you wish ie the folder name file
    and now type the 2 lines code in it and see the magic.

kode aktivitas baru bernama NoteEditor.java untuk tujuan pengeditan, aplikasi saya adalah basicley aplikasi catatan.

package com.example.elavi.notes;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import android.widget.Toast;

import static android.media.CamcorderProfile.get;
public class NoteEditorActivity extends AppCompatActivity {
    EditText editText;
    int noteid;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_note_editor);
        editText = findViewById(R.id.editText);
        Intent intent = getIntent();
         noteid = intent.getIntExtra("noteid", -1);
        if (noteid != -1) {
            String text = MainActivity.notes.get(noteid);
            editText.setText(text);

           Toast.makeText(getApplicationContext(),"The arraylist content is"+MainActivity.notes.get(noteid),Toast.LENGTH_SHORT).show();
        }
        else
        {
            Toast.makeText(getApplicationContext(),"Here we go",Toast.LENGTH_SHORT).show();
            MainActivity.notes.add("");
            noteid=MainActivity.notes.size()-1;
        }
        editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }
            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                if (noteid != -1) {
                    MainActivity.notes.set(noteid, String.valueOf(charSequence));
                    MainActivity.arrayAdapter.notifyDataSetChanged();
                }
            }
            @Override
            public void afterTextChanged(Editable editable) {

            }
        });
    }
}
Garg mewah
sumber
1

Di Kotlin cukup gunakan fungsi ekstensi KTX : (Menggunakan TextWatcher)

yourEditText.doOnTextChanged { text, start, count, after -> 
        // action which will be invoked when the text is changing
    }


impor core-KTX:

implementation "androidx.core:core-ktx:1.2.0"
Francis
sumber
1

Kami dapat menghapus TextWatcher untuk bidang sesaat sebelum mengedit teksnya lalu menambahkannya kembali setelah mengedit teks.

Nyatakan Pengamat Teks untuk field1 dan field2 sebagai variabel terpisah untuk memberi mereka nama: misalnya untuk field1

private TextWatcher Field_1_Watcher = new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    @Override
    public void afterTextChanged(Editable s) {
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

    }

};

kemudian tambahkan pengamat menggunakan namanya: field1.addTextChangedListener(Field_1_Watcher)untuk field1 , dan field2.addTextChangedListener(Field_2_Watcher)untuk field2

Sebelum mengubah teks field2 hapus TextWatcher: field2.removeTextChangedListener(Field_2_Watcher) ubah teks: field2.setText("")

kemudian tambahkan kembali TextWatcher: field2.addTextChangedListener(Field_2_Watcher)

Lakukan hal yang sama untuk bidang lainnya

Keith Kiarie
sumber
-3

Tambahkan latar belakang secara dinamis dalam onCreatemetode:

getWindow().setBackgroundDrawableResource(R.drawable.background);

juga menghapus latar belakang dari XML.

Ankit Kumar
sumber