用于多个 EditText 的 TextWatcher

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

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

然后重写我的活动中的方法:

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目前的重点。

77867 次浏览

我会这样做:

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

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

每个 EditText 都有自己的 Spannable。TextWatcher的事件将这个 Spannable 作为 s参数。我检查它们的 hashCode (每个对象的唯一 ID)。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);

是的,您可以使用存储 TextView的自定义 TextWatcher的多个实例。 (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;
}
}

当然,你也可以在 beforeTextChangedonTextChanged中使用 findTextView

所有活动的全局一类。

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


}
}

使用“ 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
}

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

另一种方法是将 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;
}
}

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

编辑

如果只想使用 after TextChanged 比较编辑器:

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

我的实施方式是:

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


}

我使用这种方法:

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

    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) {
    
    
    }
    };
    }
    
  • Add listener to multiple EditText's, you can also pass other parameters:

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

在尝试了几种方法来实现这一点,我找到了正确的方法使用 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
}
}
}

使用 HashCode ()方法比较编辑文本和字符串的哈希代码

@Override
public void afterTextChanged(Editable s) {


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


}

这就是我所做的..。

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


}

然后在 onCreate 方法中将 TextWatcher 添加到每个 EditText 中,并且在这里默认保留了按钮 setEnable (false)。

button.setEnabled(false);


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

您可以通过这种方式获取编辑文本的 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);
}

如果你正在使用 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
}
}
}
}
)
}

然后像这样将文本查看器添加到 EditText

editText1.addTextWatcher()
editText2.addTextWatcher()

我曾经做过类似的事情,只有一个 TextWatcher类来控制来自 Activity或者 FragmentEditText

您需要首先创建一个 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,因为你想像下面这样,而且我已经使用 数据绑定来获得 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) {


}
})
}