Wie verwende ich Single TextWatcher für mehrere EditTexts?

Ich habe drei EditText Widgets in meinem Ansichtslayout. Gibt es eine Möglichkeit, einen TextWatcher für alle drei EditTexts ?

    Ich bin gerade auf dieses Problem gestoßen. Ich habe es getriggers, indem ich eine innere classnimplementierung von TextWatcher , die eine Ansicht als Argument verwendet. Editable dann in der Methodenimplementierung einfach die Ansicht, um zu sehen, von welcher Editable das Editable stammt

    Erklärung:

     private class GenericTextWatcher implements TextWatcher{ private View view; private GenericTextWatcher(View view) { this.view = view; } public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {} public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {} public void afterTextChanged(Editable editable) { String text = editable.toString(); switch(view.getId()){ case R.id.name: model.setName(text); break; case R.id.email: model.setEmail(text); break; case R.id.phone: model.setPhone(text); break; } } } 

    Verwendung:

     name = (EditText) findViewById(R.id.name); name.setText(model.getName()); name.addTextChangedListener(new GenericTextWatcher(name)); email = (EditText) findViewById(R.id.email); email.setText(model.getEmail()); email.addTextChangedListener(new GenericTextWatcher(email)); phone = (EditText) findViewById(R.id.phone); phone.setText(model.getPhone()); phone.addTextChangedListener(new GenericTextWatcher(phone)); 

    Wenn Sie nur afterTextChanged-Vergleichsbearbeitungen verwenden möchten:

     @Override public void afterTextChanged(Editable editable) { if (editable == mEditText1.getEditableText()) { // DO STH } else if (editable == mEditText2.getEditableText()) { // DO STH } } 

    MultiTextWatcher Implementierung

     public class MultiTextWatcher { private TextWatcherWithInstance callback; public MultiTextWatcher setCallback(TextWatcherWithInstance callback) { this.callback = callback; return this; } public MultiTextWatcher registerEditText(final EditText editText) { editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { callback.beforeTextChanged(editText, s, start, count, after); } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { callback.onTextChanged(editText, s, start, before, count); } @Override public void afterTextChanged(Editable editable) { callback.afterTextChanged(editText, editable); } }); return this; } interface TextWatcherWithInstance { void beforeTextChanged(EditText editText, CharSequence s, int start, int count, int after); void onTextChanged(EditText editText, CharSequence s, int start, int before, int count); void afterTextChanged(EditText editText, Editable editable); } } 

    Verwendung

      new MultiTextWatcher() .registerEditText(editText1) .registerEditText(editText2) .registerEditText(editText3) .setCallback(new TextWatcherWithInstance() { @Override public void beforeTextChanged(EditText editText, CharSequence s, int start, int count, int after) { // TODO: Do some thing with editText } @Override public void onTextChanged(EditText editText, CharSequence s, int start, int before, int count) { // TODO: Do some thing with editText } @Override public void afterTextChanged(EditText editText, Editable editable) { // TODO: Do some thing with editText } }); 

    Es wird mit diesem Code arbeiten

     TextWatcher watcher = new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { //YOUR CODE } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { //YOUR CODE } @Override public void afterTextChanged(Editable s) { String outputedText = s.toString(); mOutputText.setText(outputedText); } }; 

    Dann fügen Sie dies in oncreate hinzu

      mInputText.addTextChangedListener(watcher); e2.addTextChangedListener(watcher); e3.addTextChangedListener(watcher); e4.addTextChangedListener(watcher); 

    Lassen Sie Ihre class von Activity erben und implementieren Sie TextWatcher.

    Dann, durch die Magie des Polymorphismus, müssen Sie nur die Ereignisse abonnieren.

    Dies wird dir nicht sagen, was TextEdit geändert hat, aber mit einer Kombination aus dieser und Sky Kelseys Antwort könntest du das gut sortieren.

      public YourActivity extends Activity implements TextWatcher { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_YourActivity); //Subscribe to the events EditText txt1 = (EditText) findViewById(R.id.txt1); txt1.addTextChangedListener(this); EditText txt2 = (EditText) findViewById(R.id.txt2); txt2.addTextChangedListener(this); } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { EditText txt1 = (EditText) findViewById(R.id.txt1); EditText txt2 = (EditText) findViewById(R.id.txt2); // You probably only want the text value from the EditText. But you get the idea. doStuff(txt1,txt2); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.calc, menu); return true; } @Override public void afterTextChanged(Editable s) { // TODO Auto-generated method stub } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { // TODO Auto-generated method stub } } 

    Ich weiß, das ist ein altes Problem, und es gibt eine richtige Entscheidung. Ich werde ihr eigenes schreiben, vielleicht wird es jemandem helfen.

    Emulieren des klassischen Beispiels, wo wir N EditText haben, und wir wollen die Schaltfläche anzeigen, wenn alle Felder ausgefüllt sind. Dieses Beispiel ist sinnvoll, insbesondere wenn Sie für jeden einen weiteren Validator verwenden.

    Ich habe ein Beispiel in Bezug auf das Problem gemacht, aber Sie können jedes Set machen

    MultiEditText.class

     public class MultiEditText extends AppCompatActivity{ EditText ed_1, ed_2, ed_3; Button btn_ok; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.multi_edit_text); ed_1 = (EditText) findViewById(R.id.ed_1); ed_2 = (EditText) findViewById(R.id.ed_2); ed_3 = (EditText) findViewById(R.id.ed_3); btn_ok = (Button) findViewById(R.id.btn_ok); btn_ok.setEnabled(false); //if want more here can cycle interface List 
      EditText[] edList = {ed_1, ed_2, ed_3}; CustomTextWatcher textWatcher = new CustomTextWatcher(edList, btn_ok); for (EditText editText : edList) editText.addTextChangedListener(textWatcher); 
      } } 

    Es sieht jetzt sehr einfach aus

    CustomTextWatcher.class

     public class CustomTextWatcher implements TextWatcher { View v; EditText[] edList; public CustomTextWatcher(EditText[] edList, Button v) { this.v = v; this.edList = edList; } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) {} @Override public void afterTextChanged(Editable s) { for (EditText editText : edList) { if (editText.getText().toString().trim().length() < = 0) { v.setEnabled(false); break; } else v.setEnabled(true); } } } 

    Ich werde ein Layout hinzufügen, damit du keine Zeit verschwendest

    multi_edit_text.xml

           
     TextWatcher watcher = 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) { } @Override public void afterTextChanged(Editable editable) { } }; 

    Dann:

     editText1.addTextChangedListener(watcher); editText2.addTextChangedListener(watcher); editText3.addTextChangedListener(watcher); 

    Wenn Sie onTextChanged verwenden wollen, vergleichen Sie hashCode hashCode()

     @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { if(charSequence.hashCode() == first_edit_text.getText().hashCode()){ // do other things } if(charSequence.hashCode() == second_edit_text.getText().hashCode()){ // do other things } } 

    Oder

    Wenn Sie afterTextChanged verwenden möchten, vergleichen Sie Editable das unten erwähnt wird –

     @Override public void afterTextChanged(Editable editable) { if (editable == first_edit_text.getEditableText()) { // do other things } else if (editable == second_edit_text.getEditableText()) { // do other things } } 

    Hier ist, wie ich es gemacht habe:

    Erstellen Sie eine ArrayList von EditTexts und verwenden Sie dann eine for-Schleife, um den TextWatcher für alle EditTexts anzuwenden, wenn Sie ein Verhalten für alle editTexts haben, dann wenden Sie es einfach dort an, wenn Sie bestimmte Verhaltensweisen für bestimmte editTexts haben, dann können Sie if verwenden statement zur Auswahl und Anwendung auf einzelne editTexts … hier ist mein Code:

      ArrayList editTexts = new ArrayList<>(); // Container list editText1 = (EditText) findViewById(R.id.editText1); editText2 = (EditText) findViewById(R.id.editText2); editText3 = (EditText) findViewById(R.id.editText3); editTexts.add(editText1); // editTexts[0] editTexts.add(editText2); // editTexts[1] editTexts.add(editText3); // editTexts[2] for (final EditText editText : editTexts) { //need to be final for custom behaviors editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { //Apply general behavior for all editTexts if (editText == editTexts.get(1)) { //Apply custom behavior just for this editText } } }); } 

    Hoffe das hilft

     public class MainActivity extends AppCompatActivity{ EditText value1, value2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //instantiate EditText controls value1 = (EditText)findViewById(R.id.txtValue1); value2 = (EditText)findViewById(R.id.txtValue2); //set up text changed listener value1.addTextChangedListener(new TextChange(value1)); value2.addTextChangedListener(new TextChange(value2)); //inner class private class TextChange implements TextWatcher { /** * This method is called to notify you that, within s, * the count characters beginning at start * are about to be replaced by new text with length after. * It is an error to attempt to make changes to s from * this callback. * * @param s * @param start * @param count * @param after */ View view; private TextChange (View v) { view = v; }//end constructor @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } /** * This method is called to notify you that, within s, * the count characters beginning at start * have just replaced old text that had length before. * It is an error to attempt to make changes to s from * this callback. * * @param s * @param start * @param before * @param count */ @Override public void onTextChanged(CharSequence s, int start, int before, int count) { switch (view.getId()) { case R.id.txtValue1: //insert your TextChangedListener codes here break; case R.id.txtValue2: //insert your TextChangedListener codes here break; }//end switch }//end method onTextChanged }//end inner class TextChange }//end classMainActivity 

    Ich weiß, dass diese Frage alt ist, aber ich wollte eine meiner Lösungen (in Kotlin) teilen. Meine Lösung ist eine Verbesserung von @Shwarz Andreis Antwort, mein Grund war was, wenn Sie mehr Dinge / Objekte manipulieren wollten.

    Anstatt die list of EditTexts und a Button als Parameter zu übergeben, würden Sie nur Ihre list of editText . Dann würden Sie in Ihrer benutzerdefinierten class ein Lambda wie folgt implementieren:

     var hasFilled:((Boolean)->Unit)? = null 

    Dann werden Sie es innerhalb der afterTextChanged setzen oder erhöhen

     override fun afterTextChanged(p0: Editable?) { for (edit in _editTextList) { if (edit?.text.toString().trim().isEmpty()) { hasFilled?.invoke(false) //< -- here break } else { hasFilled?.invoke(true) //<--- here } } } 

    Also jedes Mal gibt es eine Änderung in einigen EditText, die Ihr Lambda aufgerufen wird

      val editTexts = listOf(emailEditText,passwordEditText) // your list of editText val textWatcher = customTextWatcher(editTexts) // initialize your custom object editTexts.forEach { it -> it?.addTextChangedListener(textWatcher) } // each editText would listen for changes textWatcher.hasFilled = { value -> // now you have access to your lambda if (value != true) { // change the state of the button to unable // do other things } else { // change the state of the button to enable // do other things } }