android-如何删除所有使用addTextChangedListener添加的侦听器

我有一个TextWatchers,其中每一行都有一个removeTextChangedListener控件。 我想在每行中添加TextWatcher; 一个包含额外数据的数据,该数据表明TextWatcher所在的行。问题是当调用getView时,添加了多个TextWatchers; 因为convertView已经具有TextWatcher(并且指向另一个行)。

MyTextWatcher watcher = new MyTextWatcher(currentQuestion);
EditText text = (EditText)convertView.findViewById(R.id.responseText);
text.addTextChangedListener(watcher);

TextWatchers是我实现removeTextChangedListener的课程; 并处理文本事件。 CurrentQuestion让我知道我要对哪一行进行操作。 当我在方框中输入时 调用了TextWatcher的多个实例。

在添加新的TextWatchers之前,有什么方法可以删除它吗? 我看到了removeTextChangedListener方法,但这需要传递特定的TextWatcher,而且我不知道如何获取指向已经存在的TextWatcher的指针。

9个解决方案
41 votes

无法直接使用当前的ExtendedEditText520接口来执行此操作。 我看到两种可能的解决方案:

  1. 重新设计您的应用程序,使您始终知道将ExtendedEditText添加到特定的EditText实例中。
  2. 扩展ExtendedEditText,并添加清除所有观察者的可能性。

这是第二种方法的示例-ExtendedEditText

public class ExtendedEditText extends EditText
{   
    private ArrayList<TextWatcher> mListeners = null;

    public ExtendedEditText(Context ctx)
    {
        super(ctx);
    }

    public ExtendedEditText(Context ctx, AttributeSet attrs)
    {
        super(ctx, attrs);
    }

    public ExtendedEditText(Context ctx, AttributeSet attrs, int defStyle)
    {       
        super(ctx, attrs, defStyle);
    }

    @Override
    public void addTextChangedListener(TextWatcher watcher)
    {       
        if (mListeners == null) 
        {
            mListeners = new ArrayList<TextWatcher>();
        }
        mListeners.add(watcher);

        super.addTextChangedListener(watcher);
    }

    @Override
    public void removeTextChangedListener(TextWatcher watcher)
    {       
        if (mListeners != null) 
        {
            int i = mListeners.indexOf(watcher);
            if (i >= 0) 
            {
                mListeners.remove(i);
            }
        }

        super.removeTextChangedListener(watcher);
    }

    public void clearTextChangedListeners()
    {
        if(mListeners != null)
        {
            for(TextWatcher watcher : mListeners)
            {
                super.removeTextChangedListener(watcher);
            }

            mListeners.clear();
            mListeners = null;
        }
    }
}

这是如何在xml布局中使用ExtendedEditText

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <ua.inazaruk.HelloWorld.ExtendedEditText 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" 
        android:text="header"
        android:gravity="center" /> 

</LinearLayout>
inazaruk answered 2020-02-13T22:09:44Z
24 votes

您可以从EditText中删除TextWatcher。 首先,我建议您将TextWatcher声明移至editText.addTextChangedListener(...)之外:

protected TextWatcher yourTextWatcher = new TextWatcher() {

    @Override
    public void afterTextChanged(Editable s) {
        // your logic here
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        // your logic here
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
       // your logic here
    }
};

之后,您将可以更简单地设置TextWather:

editText.addTextChangedListener(yourTextWatcher);

比您可以像这样删除TextWatcher:

editText.removeTextChangedListener(yourTextWatcher);

并根据需要设置另一个。

Anton Derevyanko answered 2020-02-13T22:10:18Z
10 votes

我也花了很多时间来寻找解决方案,最后在如下标签的帮助下解决了问题。通过从convertView的标记获取引用,将删除以前的TextWatcher实例。它完美地解决了这个问题。在您的CustomAdapter文件中,设置一个新的内部类,如下所示:

private static class ViewHolder {

        private TextChangedListener textChangedListener;
        private EditText productQuantity;

        public EditText getProductQuantity() {
            return productQuantity;
        }    

        public TextChangedListener getTextChangedListener() {
            return textChangedListener;
        }

        public void setTextChangedListener(TextChangedListener textChangedListener) {
            this.textChangedListener = textChangedListener;
        }
    }

然后在您重写的公共View getView(int position,View convertView,ViewGroup parent)方法中实现以下逻辑:

@Override
public View getView(int position, View convertView, ViewGroup parent) {

     EditText productQuantity;
    TextChangedListener textChangedListener;

    if(convertView==null) {
        LayoutInflater mInflater = (LayoutInflater)
                context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        convertView = mInflater.inflate(R.layout.cart_offer_item, parent, false);

        productQuantity=(EditText)convertView.findViewById(R.id.productQuantity);
        addTextChangedListener(viewHolder, position);
        convertView.setTag(viewHolder);
    }
    else
    {
        ViewHolder viewHolder=(ViewHolder)convertView.getTag();
        productQuantity=viewHolder.getProductQuantity();
        removeTextChangedListener(viewHolder);
        addTextChangedListener(viewHolder, position);
    }

    return convertView;
}



private void removeTextChangedListener(ViewHolder viewHolder)
{
    TextChangedListener textChangedListener=viewHolder.getTextChangedListener();
    EditText productQuantity=viewHolder.getProductQuantity();
    productQuantity.removeTextChangedListener(textChangedListener);
}

private void addTextChangedListener(ViewHolder viewHolder, int position)
{
    TextChangedListener textChangedListener=new TextChangedListener(position);
    EditText productQuantity=viewHolder.getProductQuantity();
    productQuantity.addTextChangedListener(textChangedListener);
    viewHolder.setTextChangedListener(textChangedListener);
}

然后实现TextWatcher类,如下所示:

private class TextChangedListener implements TextWatcher
{
    private int position;
    TextChangedListener(int position)
    {
        this.position=position;
    }
    @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) {
    Log.d("check", "text changed in EditText");

    }
}

通过从convertView的标记获取引用,将删除以前的TextWatcher实例。

gunjot singh answered 2020-02-13T22:10:51Z
6 votes

将当前的文本监视器保存在viewholder中,您可以找到要删除的文本监视器。

Lance H answered 2020-02-13T22:11:12Z
1 votes

我在xamarin / C#中遇到了同样的问题,为此我编写了一个类来管理ListView中的单击事件,在该事件中项目视图将被“回收”:

 public class ViewOnClickEventHandler: Java.Lang.Object
 {
    private List<EventHandler> EventList { get; set; }

    public void SetOnClickEventHandler(View view, EventHandler eventHandler)
    {
        if (view.Tag != null)
        {
            ViewOnClickEventHandler holder = ((ViewOnClickEventHandler)view.Tag);

            foreach (EventHandler evH in holder.EventList)
                view.Click -= evH;

            for (int i = 0; i < holder.EventList.Count; i++)
                holder.EventList[i] = null;

            holder.EventList.Clear();
        }

        EventList = new List<EventHandler>();
        EventList.Add(eventHandler);
        view.Click += eventHandler;
        view.Tag = this;
    }
}

您可以通过以下方式在ListView BaseAdapter GetItem方法中使用它:

       TextView myTextView = convertView.FindViewById<TextView>(Resource.Id.myTextView);

        ViewOnClickEventHandler onClick = new ViewOnClickEventHandler();
        onClick.SetOnClickEventHandler(myTextView, new EventHandler(delegate (object sender, EventArgs e)
        {
            // Do whatever you want with the click event
        }));

ViewOnClickEventHandler类将关注文本视图上的多个事件。 您还可以更改textchange事件的类。 这是相同的原则。我希望这将有所帮助。

再见nxexo007

nxexo007 answered 2020-02-13T22:11:46Z
1 votes

我没有扩展TextView类就解决了这种情况。

private ArrayList<TextWatcher> mEditTextWatcherList = new ArrayList<>();
private TextWatcher mTextWatcher1;
private TextWathcer mTextWatcher2;

mTextWathcer1 = 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) {}
};

mTextWathcer2 = 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) {}
};

@Override 
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity);

    setListener(mTextWatcher1);
    setListener(mTextWatcher2);

    removeListeners();
}

private setListener(TextWatcher listener) {
    mEditText.addTextChangedListener(listener);
    mEditTextWatcherList.add(listener);
}

private removeListeners() {
    for (TextWatcher t : mEditTextWatcherList)
        mEditText.removeTextChangedListener(t);

    mEditTextWatcherList.clear();
}
Luiz Henrique Alegria answered 2020-02-13T22:12:06Z
0 votes

如您所见:TextView的CodeSearch无法删除所有侦听器。 唯一的方法是提供您用来注册的观察者。

我尚未完全理解为什么已经注册了其他侦听器。 但是,您可以继承EditText的子类,重写addTextChangedListener(..),并在其中保留所有添加的引用的副本,然后委派给超类实现。 然后,您还可以提供其他方法来删除所有侦听器。

如果您需要进一步的说明,请与我们联系。

icyerasor answered 2020-02-13T22:12:35Z
0 votes

我删除文本观察器的操作非常简单。 我创建了一个数组来放置我的文本监视器:

final TextWatcher[] textWatchers = new TextWatcher[3];

我在以下位置添加了它们:

final int CURRENT_PIN_CHECK = 0, NEW_PIN = 1, CONFIRM_PIN_CHECK = 2;

textWatchers[CURRENT_PIN_CHECK] = returnTextWatcherCheckPIN(CURRENT_PIN_CHECK);
textWatchers[NEW_PIN] = returnTextWatcherCheckPIN(NEW_PIN);
textWatchers[CONFIRM_PIN_CHECK] = returnTextWatcherCheckPIN(CONFIRM_PIN_CHECK);

我的returnTextWatcherCheckPIN方法在afterTextChanged上使用另一个检查器(switchMethod来检查所有四个editTexts)实例化textWatcher。

然后,每当我删除文本观察器时,我都只是从数组中引用了它:

etPin4.removeTextChangedListener(textWatchers[CURRENT_PIN_CHECK]);

在调试时检查editText的侦听器大小:

enter image description here

它被删除了! 那解决了我的问题!

Kim Montano answered 2020-02-13T22:13:17Z
0 votes

我遇到了类似的问题。 我通过在ArrayList792中保存对textWatchers的引用来解决此问题:

private final List<TextWatcher> textWatchersForProfileNameTextBox = new ArrayList<>();

public void addTextWatcherToProfileNameTextBox(TextWatcher textWatcher){
    textWatchersForProfileNameTextBox.add(textWatcher);
    getProfileNameTextView().addTextChangedListener(textWatcher);
}

public void removeAllTextWatchersFromProfileNameTextView(){
    while (!textWatchersForProfileNameTextBox.isEmpty())
        getProfileNameTextView().removeTextChangedListener(textWatchersForProfileNameTextBox.remove(0));
}
vatbub answered 2020-02-13T22:13:37Z
translate from https://stackoverflow.com:/questions/6270484/how-to-remove-all-listeners-added-with-addtextchangedlistener