50

Ich möchte die TextWatcher Schnittstelle für mehr als eine EditText Felder implementieren. Derzeit bin ich mit:TextWatcher für mehr als einen EditText

text1.addTextChangedListener(this); 
text2.addTextChangedListener(this); 

dann in meiner Tätigkeit die Methoden überschreiben:

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) 
{ 
// do some operation on text of text1 field 
// do some operation on text of text2 field 
} 

Doch dieses feinen funktioniert, aber ich bin auf der Suche nach anderen Möglichkeiten, so dass ich ausdrücklich, dass identifizieren, in denen EditText Feld der ist derzeit konzentriert.

+1

Mögliche Duplikat [Wie Einzel TextWatcher für mehrere EditTexts benutzen?] (Http://stackoverflow.com/questions/5702771/how-to-use-single-textwatcher-for-multiple-edittexts) –

+1

@SkyKelsey Die Antwort, die du geschrieben hast, erstellt tatsächlich mehrere Instanzen von TextWatcher, daher denke ich, dass das nicht die perfekte Antwort auf das ist, was von OP gefragt wurde, meine Frage bezieht sich auf das Identifizieren der einzelnen EditText in einer TextWatcher-Methode. –

+0

https://github.com/henrychuangtw/AutoInsertEditText – HenryChuang

Antwort

66

vorgeschlagene Lösung in @Sebastian Roth's answer einige EditTexts nicht eine Instanz TextWatcher für ist. Es ist eine Klasse und n Instanzen dieser Klasse für n EditTexts.

Jeder EditText hat seine eigene Spannable. TextWatcher Ereignisse hat diese spannbar als s Parameter. Ich überprüfe ihren HashCode (eindeutige ID jedes Objekts). myEditText1.getText() gibt das Spannable zurück. Also, wenn die myEditText1.getText().hashCode() mit s.hashCode() gleich bedeutet es, dass s gehört myEditText1

Also, wenn Sie eine Instanz von TextWatcher für einige EditTexts haben wollen Sie diese verwenden sollen:

private TextWatcher generalTextWatcher = new TextWatcher() {  

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

     if (myEditText1.getText().hashCode() == s.hashCode()) 
     { 
      myEditText1_onTextChanged(s, start, before, count); 
     } 
     else if (myEditText2.getText().hashCode() == s.hashCode()) 
     { 
      myEditText2_onTextChanged(s, start, before, count); 
     } 
    } 

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

     if (myEditText1.getText().hashCode() == s.hashCode()) 
     { 
      myEditText1_beforeTextChanged(s, start, count, after); 
     } 
     else if (myEditText2.getText().hashCode() == s.hashCode()) 
     { 
      myEditText2_beforeTextChanged(s, start, count, after); 
     } 
    } 

    @Override 
    public void afterTextChanged(Editable s) { 
     if (myEditText1.getText().hashCode() == s.hashCode()) 
     { 
      myEditText1_afterTextChanged(s); 
     } 
     else if (myEditText2.getText().hashCode() == s.hashCode()) 
     { 
      myEditText2_afterTextChanged(s); 
     } 
    } 

}; 

und

myEditText1.addTextChangedListener(generalTextWatcher); 
myEditText2.addTextChangedListener(generalTextWatcher); 
+0

Haben Sie diese Lösung überprüft? Was passiert, wenn ein Benutzer in beiden Eingabefeldern denselben Text eingibt? –

+11

@SebastianRoth Jeder EditText hat sein eigenes spannbares. 'TextWatcher'-Events haben dieses Spannable als' CharSequence' oder 'Editable' Parameter. Ich überprüfe nicht den Textwert von EditTexts. Ich überprüfe ihren HashCode (eindeutige ID jedes Objekts). 'myEditText1.getText()' gibt 'Spannable' zurück, nicht den Textwert. Also, wenn die 'myEditText1.getText(). HashCode()' ist gleich mit 's.hashCode()' bedeutet, dass s gehört zu 'myEditText1' – breceivemail

+3

Sie haben Recht, sehr gut. Danke für die Zugabe! –

75

Ich würde es tun, wie folgt:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    EditText e = new EditText(this); 
    e.addTextChangedListener(new CustomTextWatcher(e)); 
} 

private class CustomTextWatcher implements TextWatcher { 
    private EditText mEditText; 

    public CustomTextWatcher(EditText e) { 
     mEditText = e; 
    } 

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

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

    public void afterTextChanged(Editable s) { 
    } 
} 
+4

Interessante Idee, aber das bedeutet, dass Sie einen separaten Text Watcher für jeden EditText haben. – ArtOfWarfare

+10

Diese Antwort ist nicht 'Single TextWatcher für mehrere EditTexts'. Es sind 3 Instanzen einer TextWatcher-Klasse. So steuern 3 separate TextWatchers 3 EditTexts. – breceivemail

+1

@breceivemail, eine Klasse, 3 Instanzen. Vereinbart ist es schwierig, wenn Menschen ihren Objekttyp nicht angeben. Sein Ziel war es, den Code nur einmal zu schreiben, also ist es so. – SparK

1

Ja, Sie könnten mehrere Instanzen einer benutzerdefinierten TextWatcher verwenden, die die TextView speichert. (TextView ist eigentlich die Klasse, die addTextChangedListener hat.)

ähnlich wie bei der hashCode Lösung über Sie nur, wenn getText()==s überprüfen. Anstatt alle Ihre Steuerelemente oder findViewById mehrmals zu speichern, können Sie einfach den Inhaltsbaum selbst einmal für das Steuerelement mit der CharSequence scannen.

public TextView findTextView(View v, CharSequence s) 
{ 
    TextView tv; 
    ViewGroup vg; 
    int i, n; 

    if (v instanceof TextView) 
    { 
     tv = (TextView) v; 
     if (tv.getText()==s) return(tv); 
    } 

    else if (v instanceof ViewGroup) 
    { 
     vg = (ViewGroup) v; 
     n = vg.getChildCount(); 
     for(i=0;i<n;i++) 
     { 
     tv = findTextView(vg.getChildAt(i), s); 
     if (tv!=null) return(tv); 
     } 
    } 

    return(null); 
} 

public void afterTextChanged(Editable s) 
{ 
    TextView tv=findTextView(findViewById(android.R.id.content), s); 
    if (tv==null) return; 
    switch(tv.getId()) 
    { 
     case R.id.path: 
     break; 
     case R.id.title: 
     break; 
    } 
} 

Natürlich könnte man auch findTextView innerhalb beforeTextChanged und onTextChanged verwenden.

+0

Wunderbare Lösung. Es kann den EditText identifizieren, den ich bearbeite, wenn er innerhalb von TextWatcher überschriebenen Methoden verwendet wird. Können Sie ein wenig erklären, wie Sie zu dieser Lösung gekommen sind und 'findViewById (android.R.id.content) verwendet haben, um die Bearbeitungsansicht zu erhalten? –

+0

'findViewById (android.R.id.Inhalt) 'ist ein bisschen übertrieben, es bekommt Sie die' ViewGroup', die Ihren Inhalt hält. Es ist besser, die niedrigste "ViewGroup" auszuwählen, die alle interessanten Dinge enthält. – Renate

1

Global Eine Klasse für alle Aktivitäten.

CustomTextWatcher.java

package org.logicbridge.freshclub.customizedItems; 

import android.content.Context; 
import android.text.Editable; 
import android.text.TextWatcher; 
    public class CustomTextWatcher implements TextWatcher { 
     private EditText mEditText; 
     Context context; 

     public CustomTextWatcher(EditText e, Context context) { 
      mEditText = e; 
      this.context = context; 
     } 

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

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

     public void afterTextChanged(Editable s) { 

     } 
    } 
11

"CustomTextWatcher" Idee mit, ich getan, dass

1) eine neue TextWatcherListener Schnittstelle crated:

public interface TextWatcherExtendedListener extends NoCopySpan 
{ 
    public void afterTextChanged(View v, Editable s); 

    public void onTextChanged(View v, CharSequence s, int start, int before, int count); 

    public void beforeTextChanged(View v, CharSequence s, int start, int count, int after); 
} 

2) erstellt und verwendet statt EditText (in meinem Fall EditTextExtended):

public class EditTextExtended extends EditText 
{ 
    private TextWatcherExtendedListener mListeners = null; 

    public EditTextExtended(Context context) 
    { 
    super(context); 
    } 

    public EditTextExtended(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 
    } 

    public EditTextExtended(Context context, AttributeSet attrs, int defStyle) 
    { 
     super(context, attrs, defStyle); 
    } 

    public void addTextChangedListener(TextWatcherExtendedListener watcher) 
    {  
     if (mListeners == null) 
     { 
      mListeners = watcher; 
     } 
    } 

    public void removeTextChangedListener(TextWatcherExtendedListener watcher) 
    { 
     if (mListeners != null) 
     { 
      mListeners = null;   
     } 
    } 

    void sendBeforeTextChanged(CharSequence text, int start, int before, int after) 
    { 
     if (mListeners != null) 
     { 
      mListeners.beforeTextChanged(this, text, start, before, after); 
     } 
    } 

    void sendOnTextChanged(CharSequence text, int start, int before,int after) 
    { 
     if (mListeners != null) 
     { 
      mListeners.onTextChanged(this, text, start, before, after); 
     } 
    } 

    void sendAfterTextChanged(Editable text) 
    { 
     if (mListeners != null) 
     { 
      mListeners.afterTextChanged(this, text); 
     } 
    } 
} 

3) Also, wo Sie diesen Code benötigen schreiben:

myEditTextExtended.addTextChangedListener(this) //Let implement TextWatcherExtendedListener methods 

4) verwenden sie:

@Override 
public void onTextChanged(View v, CharSequence s, int start, int before, int count) 
{ 
    //Tested and works 
    //do your stuff 
} 


@Override 
public void beforeTextChanged(View v, CharSequence s, int start, int count, int after) 
{ 
    //not yet tested but it should work  
} 

@Override 
public void afterTextChanged(View v, Editable s) 
{ 
    //not yet tested but it should work 
} 

Nun, lassen Sie mich wissen, was denken Sie.

+0

Ich denke, dies ist der einfachste Weg zu diesem Thema. +1 – AustrianDude

2

Eine weitere Möglichkeit ist um OnClickListener-EditText hinzuzufügen und eine globale Variable wie unten angegeben

EditText etCurrentEditor;//Global variable 

@Override 
    public void onClick(View v) { 
     // TODO Auto-generated method stub 
     if(v instanceof EditText){ 
      etCurrentEditor=(EditText)v; 
     } 
    } 

verwenden etCurrentEditor als Referenz editiert derzeit EditText

@Override 
    public void afterTextChanged(Editable editable) { 
     // TODO Auto-generated method stub 
     switch (etCurrentEditor.getId()) { 
     case R.id.EDITTEXTID: 
      break; 
     default: 
      break; 
     } 
    } 
0

Sie können jederzeit definieren TextWatcher als Parameter zu Methode. Auf diese Weise können Sie mehrere Definitionen für jeden Text bearbeiten.

+0

Aber Sie können keinen Verweis auf EditText in TextWatcher bekommen ... – Sver

8

--EDIT--

Wenn Sie nur verwenden afterTextChanged editables vergleichen:

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

Geht das nicht davon aus, dass es nie den gleichen Text in mehreren EditText Ansichten geben wird? Abhängig von der App, die möglicherweise keine gültige Annahme ist. – RenniePet

+0

@RenniePet Bitte schauen Sie sich die neue Version des Codes an. – Tomasz

+0

Verdammt, es tut mir sehr leid, aber ich bin jetzt überzeugt, dass ich falsch lag. Ich denke jetzt, dass sowohl Ihre Originalversion als auch die bearbeitete Version korrekt sind - Sie vergleichen das von EditText.getEditableText() zurückgegebene Java-Objekt mit dem bereitgestellten Editable-implementierenden Objekt, nicht die beteiligten Texte. (In meinen Tests scheinen die beiden Objekte immer ein SpannableStringBuilder-Objekt zu sein und Googles Dokumentation für SpannableStringBuilder.equals() sagt klar, dass es Objekte vergleicht, nicht den enthaltenen Text.) – RenniePet

1

I umgesetzt als:

edittext1.addTextChangedListener(this); 
edittext2.addTextChangedListener(this); 
edittext3.addTextChangedListener(this); 

und:

@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(edittext1.hasFocus()){ 
     //text changed for edittext1 
    }else if(edittext2.hasFocus()){ 
     //text changed for edittext2 
    }else { 
     //text changed for edittext3 
    } 
} 

@Override 
public void afterTextChanged(Editable editable) { 

} 
3

Ich benutze diese Lösung:

  • Add-Methode, die Zuhörer zurück:

    private TextWatcher getTextWatcher(final EditText editText) { 
        return 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) { 
          // do what you want with your EditText 
          editText.setText("blabla"); 
         } 
    
         @Override 
         public void afterTextChanged(Editable editable) { 
    
         } 
        }; 
    } 
    
  • hinzufügen Zuhörer auf mehrere EditText ist, können Sie auch andere Parameter übergeben:

    editText1.addTextChangedListener(getTextWatcher(editText1)); 
    editText2.addTextChangedListener(getTextWatcher(editText2)); 
    editText3.addTextChangedListener(getTextWatcher(editText3)); 
    
+0

Beste immer ans ... nichts im Code ändern. danke dir so viel –

+0

Einfach und daher die "beste Antwort" – Vibhav

1

Nach versuchen Sie mehrere Möglichkeiten, dies zu erreichen, finde ich den richtigen Weg mit EditText.isFocused() zu unterscheiden.Zum Beispiel:

private class OnTextChangedListener implements 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) { 
     if (edtName.isFocused()) { 
      //do something 
     } else if (edtEmail.isFocused()) { 
      //do something 
     } else if (edtContent.isFocused()) { 
      //do something 
     } 
    } 
} 
0

nur Hash-Codes der EditText und String wie durch die Verwendung hashCode() Methode

@Override 
public void afterTextChanged(Editable s) { 

    if (editext.getText().hashCode() == s.hashCode()){ 
     type1Total(type1List); 
    } 

} 
0

vergleichen Dies ist, was ich getan habe ...

private TextWatcher textWatcher = 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) { 

     if (editText1.getText().length() > 0 
       && editText2.getText().length() > 0 
       && editText3.getText().length() > 0) { 

      button.setEnabled(true); 
     } else { 

      button.setEnabled(false); 
     } 

    } 

    @Override 
    public void afterTextChanged(Editable s) { 

    } 

Dann hinzugefügt den TextWatcher zu jedem EditText in der OnCreate-Methode & auch gehalten die Schaltfläche setEnabled (false) als Standard hier.

button.setEnabled(false); 

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