TextWatcher用于多个EditText


73

我想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



1
@SkyKelsey您写的答案实际上是在创建TextWatcher的多个实例,因此,我认为这不是OP所要求的完美答案,因为我的问题是要确定TextWatcher接口方法中的每个EditText。
维卡斯·帕蒂达

Answers:


96

在建议的解决方案@Sebastian罗斯的回答是没有的一个实例TextWatcher一些EditTexts。它是一个类,并且该类的n个实例对应n EditTexts

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

3
您是否仔细检查过此解决方案?如果用户在两个输入字段中输入相同的文本会怎样?
塞巴斯蒂安·罗斯

15
@SebastianRoth每个EditText都有自己的Spannable。TextWatcher事件具有此Spannable asCharSequenceEditable参数。我不检查EditTexts的Text值。我检查他们的hashCode(每个对象的唯一ID)。myEditText1.getText()返回的Spannable不是Text值。因此,如果myEditText1.getText().hashCode()等于s.hashCode()表示s属于myEditText1
Bobs 2012年

1
好的,谢谢您的编辑。但是现在我还有另一个问题。(我是Android和Java的新手,所以请您忍受。)我不明白您为什么要使用hashCode()方法来测试可扩展对象是否为同一对象。为什么不只将它们与“ ==”进行比较?(在C#中,我将使用ObjectEquals(),但在Java中,仅使用==,对吧?)
RenniePet 2014年

1
这是一个不好的解决方案。一旦两个EditText具有相同的字符串,它将立即失败,因为它在内存中将是相同的字符串(因此是相同的哈希码)。
Eurig Jones

1
您确定所有哈希值都是唯一的吗?哈希冲突呢?
miva2 2015年

87

我会这样:

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

6
有趣的主意,但这意味着您对每个EditText都有单独的文本监视程序。
ArtOfWarfare 2012年

13
这个答案不是Single TextWatcher for multiple EditTexts。它是一个TextWatcher类的3个实例。因此,三个独立的TextWatcher控制着三个EditText。
Bobs

1
@breceivemail,一个类,三个实例。同意当人们不指定对象类型时很难。他的目标是只编写一次代码,因此就可以了。
SparK

这有什么习惯呢?我不明白
r3dm4n

@Bobs,我想创建3个对象比编写一个对象更容易,并支持它的未来更改更加容易。
CoolMind

13

我使用以下解决方案:

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

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

有史以来最好的...代码没改变。非常感谢您
Vishal Patel

简单,因此是“最佳答案”
Vibhav

像魅力一样工作。
Kunwar Shekhar Singh,

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 
}

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


我认为这是解决此问题的最直接方法。+1
AustrianDude

12

- 编辑 -

如果只想使用afterTextChanged比较可编辑内容:

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

1
这不是假设多个EditText视图中永远不会有相同的文本吗?取决于应用程序,这可能不是有效的假设。
RenniePet 2014年

该死,我很抱歉,但是我现在确信我错了。我现在认为您的原始版本和编辑版本都是正确的-您正在将EditText.getEditableText()返回的Java对象与提供的Editable-implementing对象进行比较,而不是将涉及的文本进行比较。(在我的测试中,这两个对象似乎始终是SpannableStringBuilder对象,而Google针对SpannableStringBuilder.equals()的文档清楚地表明,它是比较对象而不是包含的文本。)
RenniePet 2014年

@RenniePet我的答案的第一个版本是错误的。我们不应该比较编辑文本的值。现在效果很好。我看到我的答案应该在该线程的顶部。
Tomasz 2014年

出于某种原因,这是工作在我的模拟器,但不是真正的设备,最后,这个答案为我工作:stackoverflow.com/a/13787221/2263329比较hashCode()Editable
Mahmudul Hasan Shohag

2

还有一个办法解决是添加OnClickListenerEditText并设置一个全局变量下面给出

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

2

我将其实现为:

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

}

2

在尝试了几种方法来实现这一目标之后,我找到了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
        }
    }
}

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


很棒的解决方案。当在TextWatcher重写的方法中使用它时,它可以标识正在编辑的EditText。您能否解释一下如何使用此解决方案并使用`findViewById(android.R.id.content)获取编辑视图?
Randika Vishman '16

findViewById(android.R.id.content)有点矫kill过正,它会使ViewGroup您拥有内容。最好选择能ViewGroup容纳所有文本更改内容的最低点。
重现

1

全球所有活动的一堂课。

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

        }
    }

1

您可以执行此操作以获取编辑文本的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);
}

0

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


0

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

@Override
public void afterTextChanged(Editable s) {

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

}

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上,并在此处默认情况下还保留按钮setEnabled(false)。

button.setEnabled(false); 

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

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

然后像这样将textwatcher添加到EditTexts

editText1.addTextWatcher()
editText2.addTextWatcher()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.