如何使用单个TextWatcher的多个EditTexts?

我的视图布局中有三个EditText小部件。 有没有办法为所有三个EditTexts使用一个TextWatcher

我刚刚遇到这个问题。 我通过创build一个将View作为参数的TextWatcher的内部类实现来TextWatcher这个问题。 然后,在方法实现中,只需打开视图来查看Editable来自哪一个

宣言:

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

用法:

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

如果你只想使用afterTextChanged compare编辑器:

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

它将与这个代码一起工作

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

然后添加这个在创build

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

MultiTextWatcher实现

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

用法

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

让你的类inheritance自Activity并实现TextWatcher。

然后通过多态的魔力,你只需要订阅事件。

这不会告诉你TextEdit是怎么改变的,但是结合使用这个和Sky Kelsey的答案,你可以很好的分类。

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

我知道这是一个老问题,有一个正确的决定。 我会写自己的,也许会帮助别人。

仿真我们有N个EditText的经典例子,并且如果所有的字段都被填充,我们想显示button。 这个例子是有道理的,特别是如果进一步使用每个validation器。

我就这个问题做了一个例子,但是你可以做任何设置

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

现在看起来很简单

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

我会添加一个布局,所以你不会浪费时间

multi_edit_text.xml

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp"> <EditText android:id="@+id/ed_1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="8dp" /> <EditText android:id="@+id/ed_2" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/ed_1" android:layout_centerHorizontal="true" android:layout_marginTop="8dp" /> <EditText android:id="@+id/ed_3" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/ed_2" android:layout_centerHorizontal="true" android:layout_marginTop="8dp" /> <Button android:id="@+id/btn_ok" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/ed_3" android:layout_centerHorizontal="true" android:layout_marginTop="8dp" android:text="OK" /> </RelativeLayout> 
 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) { } }; 

然后:

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

我是这样做的:

创build一个EditTexts的ArrayList,然后使用for循环来为所有的EditTexts应用TextWatcher,如果你对所有的editTexts有一个行为,那么就把它应用到那里,如果你对某些特定的editTexts有特定的行为,那么你可以使用if语句来select并应用到单个editTexts …这是我的代码:

  ArrayList<EditText> 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 } } }); } 

希望这可以帮助

 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 <code>s</code>, * the <code>count</code> characters beginning at <code>start</code> * are about to be replaced by new text with length <code>after</code>. * It is an error to attempt to make changes to <code>s</code> 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 <code>s</code>, * the <code>count</code> characters beginning at <code>start</code> * have just replaced old text that had length <code>before</code>. * It is an error to attempt to make changes to <code>s</code> 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 

我知道这个问题很老,但我想分享一个我的解决scheme(在Kotlin)。 我的解决scheme是对@Shwarz Andrei的回答的改进,我的理由是如果你想操纵更多的东西/对象。

不要将list of EditTextsa Button list of EditTexts作为parameter passing,只能传递list of editTextlist of editText 。 然后在你的自定义类中,你会实现一个lambda:

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

然后,您将在afterTextChanged设置或提高它

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

所以每一次,你的lambda被调用的EditText都会发生变化

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

如果你想使用onTextChanged比较下面提到的 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 } } 

要么

如果你想使用afterTextChanged比较下面提到的 Editable

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