TextWatcher用于多个EditText

时间:2010-11-26 06:43:08

标签: android interface android-activity android-edittext textwatcher

我想为多个TextWatcher字段实现EditText接口。目前我正在使用:

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

然后覆盖我的Activity中的方法:

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 
}

然而,这工作正常,但我正在寻找其他方法,以便我可以明确指出EditText字段当前所关注的SoftKeyboard字段。

16 个答案:

答案 0 :(得分:84)

@Sebastian Roth's answer中的建议解决方案不是某些TextWatcher EditTexts的一个实例。对于n EditTexts,它是该类的一个类和n个实例。

每个EditText都有自己的Spannable。 TextWatcher的事件将此Spannable作为s参数。我检查他们的hashCode(每个对象的唯一ID)。 myEditText1.getText()返回Spannable。因此,如果myEditText1.getText().hashCode()s.hashCode()相等,则表示s属于myEditText1

因此,如果您想为某些TextWatcher设置一个EditTexts实例,则应使用此功能:

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

};

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

答案 1 :(得分:82)

我会这样做:

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

答案 2 :(得分:12)

使用“CustomTextWatcher”的想法,我做到了

1)创建一个新的TextWatcherListener接口:

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)创建并使用了EditTextExtended而不是EditText(在我的例子中):

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)所以,你需要写下这段代码:

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

4)使用它们:

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

好吧,让我知道你的想法。

答案 3 :(得分:11)

<强> - 编辑 -

如果您只想使用afterTextChanged比较editables:

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

答案 4 :(得分:7)

我使用这个解决方案:

  • 添加返回侦听器的方法:

    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) {
    
            }
        };
    }
    
  • 将监听器添加到多个EditText,您还可以传递其他参数:

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

答案 5 :(得分:2)

另一种方法是将OnClickListener添加到EditText并设置一个全局变量,如下所示

EditText etCurrentEditor;//Global variable

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

使用此etCurrentEditor作为对当前编辑的EditText的引用

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

答案 6 :(得分:1)

是的,您可以使用存储TextWatcher的自定义TextView的多个实例。 (TextView实际上是具有addTextChangedListener的类。)

与上面的hashCode解决方案类似,您只需检查是否getText()==s。 您可以自行扫描内容树一次以获取具有findViewById的控件,而不是多次存储所有控件或CharSequence

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

当然,您也可以在findTextViewbeforeTextChanged内使用onTextChanged

答案 7 :(得分:1)

所有活动的Global One课程。

<强> 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) {

        }
    }

答案 8 :(得分:1)

我将其实现为:

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

@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) {

}

答案 9 :(得分:1)

在尝试了几种实现这一目标的方法之后,我找到了使用EditText.isFocused()来区分彼此的正确方法。例如:

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

答案 10 :(得分:0)

您始终可以将TextWatcher定义为addTextChangedListener方法的参数。这样,​​每个编辑文本都可以有多个定义。

答案 11 :(得分:0)

只需使用 hashCode()方法比较edittext和字符串的哈希码

@Override
public void afterTextChanged(Editable s) {

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

}

答案 12 :(得分:0)

这就是我所做的......

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

    }

然后将TextWatcher添加到onCreate方法中的每个EditText&amp;默认情况下也保持按钮setEnabled(false)。

button.setEnabled(false); 

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

答案 13 :(得分:0)

您可以执行此操作以获取编辑文本的ID。它没有经过测试,但是让我知道它是否有效。

//setting textWatcher for the editText
textWatcher(owner_name);


public void textWatcher(final EditText editText){

    TextWatcher watcher = new TextWatcher() {
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

           if(editText.getId()==R.id.your_id){
             //Do something
           }   
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
          if(editText.getId()==R.id.your_id){
          //Do something
          }
        }

        @Override
        public void afterTextChanged(Editable s) { }
    };

    editText.addTextChangedListener(watcher);
}

答案 14 :(得分:0)

如果您使用的是Kotlin,扩展功能将完成此工作。 例如,我们需要将TextWatcher添加到editText1editText2

创建这样的扩展功能,

 fun EditText.addTextWatcher() {
        this.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) {
                        // you do some common operations here

                        when (this@addTextWatcher) {
                            editText1 -> {
                                // do something for editText1
                            }
                            editText2 -> {
                                // do something for editText2
                            }
                        }
                    }
                }
        )
    }

然后只需将文本监视器添加到EditTexts中

editText1.addTextWatcher()
editText2.addTextWatcher()

答案 15 :(得分:0)

我做了这样的事情,只有一个 TextWatcher 类来控制来自 EditTextActivityFragment

您需要先创建一个 MultiTextWatcher 类,如下所示

class MultiTextWatcher {

    private var callback: TextWatcherWithInstance? = null

    fun setCallback(callback: TextWatcherWithInstance): MultiTextWatcher {
        this.callback = callback
        return this
    }


    fun registerEditText(editText: EditText): MultiTextWatcher {
        editText.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
                callback!!.beforeTextChanged(editText, s, start, count, after)
            }

            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
                callback!!.onTextChanged(editText, s, start, before, count)
            }

            override fun afterTextChanged(editable: Editable) {
                callback!!.afterTextChanged(editText, editable)
            }
        })

        return this
    }

     interface TextWatcherWithInstance {
        fun beforeTextChanged(editText: EditText, s: CharSequence, start: Int, count: Int, after: Int)

        fun onTextChanged(editText: EditText, s: CharSequence, start: Int, before: Int, count: Int)

        fun afterTextChanged(editText: EditText, editable: Editable)
    }
}

然后在您的 ActivityFragment 中,您需要注册尽可能多的 EditText,如下所示,而且我已经使用 Data Binding 来获取XML 视图,您可以使用自己的方式。

 private fun setTextWatchers() {
        MultiTextWatcher()
            .registerEditText(binding.etCompanyAddress)
            .registerEditText(binding.etCompanyIntro)
            .registerEditText(binding.etCompanyName)
            .registerEditText(binding.etCompanyPhone)
            .setCallback(object : MultiTextWatcher.TextWatcherWithInstance {
                override fun beforeTextChanged(editText: EditText, s: CharSequence, start: Int, count: Int, after: Int) {
                }

                override fun onTextChanged(editText: EditText, s: CharSequence, start: Int, before: Int, count: Int) {
                    when (editText) {
                        binding.etCompanyAddress -> {
                            //do your logic here
                        }
                        binding.etCompanyPhone -> {
                            //do your logic here and so on
                        }
                    }
                }

                override fun afterTextChanged(editText: EditText, editable: Editable) {

                }
            })
    }