如何删除添加了addTextChangedListener的所有侦听器

Gen*_*ari 52 android listview textwatcher android-edittext

我有一个ListView每行有EditText控件的地方.我想在TextChangedListener每一行添加一个; 一个包含额外数据的数据,它说明了哪一行EditText.问题是,当getView被调用时,TextWatchers会添加多个; 因为convertView已经有一个TextWatcher(和一个指向不同的行).

MyTextWatcher watcher = new MyTextWatcher(currentQuestion);
EditText text = (EditText)convertView.findViewById(R.id.responseText);
text.addTextChangedListener(watcher);
Run Code Online (Sandbox Code Playgroud)

MyTextWatcher是我的班级实施TextWatcher; 并处理文本事件.CurrentQuestion让我知道我正在采取哪一行.当我输入框中; TextWatcher调用多个实例.

有没有办法TextWatchers在添加新的之前删除它?我看到了removeTextChangedListener方法,但这需要TextWatcher传入一个特定的,我不知道如何获得指针TextWatcher已经存在的指针.

ina*_*ruk 42

EditText直接使用当前界面无法做到这一点.我看到两种可能的解决方案

  1. 重新设计您的应用程序,以便始终了解TextWatcher添加到特定EditText实例的内容.
  2. 扩展EditText并增加清除所有观察者的可能性.

以下是第二种方法的示例 - 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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是如何ExtendedEditText在xml布局中使用:

<?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>
Run Code Online (Sandbox Code Playgroud)


Ant*_*nko 26

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

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
    }
};
Run Code Online (Sandbox Code Playgroud)

之后,您将能够更简单地设置TextWather:

editText.addTextChangedListener(yourTextWatcher);
Run Code Online (Sandbox Code Playgroud)

你可以像这样删除TextWatcher:

editText.removeTextChangedListener(yourTextWatcher);
Run Code Online (Sandbox Code Playgroud)

并根据需要设置另一个.

  • 但这意味着您必须知道应用于EditText的确切textWatcher名称.我相信问题是如何删除EditText上的所有textWatchers. (4认同)
  • 伊戈尔·加纳波尔斯基(Igor Ganapolsky),您是对的。但是在许多其他情况下,这是非常有用的东西 (2认同)
  • @IgorGanapolsky 正确。但是,我无法想到在单个 EditText 上需要多个文本观察器的情况......多个 EditText 的一个文本观察器是可以理解的,但为什么单个 EditText 需要多个文本观察器? (2认同)

gun*_*ngh 10

我也花了很多时间找到解决方案,最后在下面的标签的帮助下最终解决了.它将通过从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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

然后在你的覆盖公共视图中,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);
}
Run Code Online (Sandbox Code Playgroud)

然后实现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");

    }
}
Run Code Online (Sandbox Code Playgroud)

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


Dav*_*avi 8

这个问题已经问了很久了,但有人可能会发现这很有用。Recyclerview 中 TextWatcher 的问题是我们必须确保在视图回收之前将其删除。否则,我们会丢失 TextWatcher 的实例,并且在 OnBindViewHolder() 中调用removeTextChangedListener(textWatcher)只会删除 TextWatcher 的当前实例。

我解决这个问题的方法是将 TextChangedListener 添加到 FocusChangedListener 中:

editText.setOnFocusChangeListener(new OnFocusChangeListener() {          
public void onFocusChange(View v, boolean hasFocus) {
    if(hasFocus) {
        editText.addTextChangedListener(textWatcher)
    }
    else{
        editText.removeTextChangedListener(textWatcher)
    }
  }
});
Run Code Online (Sandbox Code Playgroud)

这样,我确信当 editText 没有焦点时,文本观察器就会被删除,并在获得焦点时再次添加。因此,当 recyclerview 被回收时,editText 将删除所有 textChangeListener。


Lan*_*e H 6

将当前的textwatcher保存在viewholder中,您可以找到要删除的文本.

  • 如果将当前文本观察器保存在视图保持器中 - 下次重新使用视图保持器时,它将有另一个视图和旧的文本观察器。因此,人们将无法从旧视图(现在属于某个其他视图持有者)中删除旧文本观察器。 (3认同)

Wen*_*aus 6

我在 RecyclerView 中的许多 EditText 中遇到了类似的问题。我通过反思解决了它。ReflectionTextWatcher.removeAll(your_edittext)在绑定视图之前调用。这段代码找到所有 TextWatchers 并将它们从本地 EditText 的名为“mListeners”的列表中删除。

public class ReflectionTextWatcher {
    public static void removeAll(EditText editText) {
        try {
            Field field = findField("mListeners", editText.getClass());
            if (field != null) {
                field.setAccessible(true);
                ArrayList<TextWatcher> list = (ArrayList<TextWatcher>) field.get(editText); //IllegalAccessException
                if (list != null) {
                    list.clear();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private static Field findField(String name, Class<?> type) {
        for (Field declaredField : type.getDeclaredFields()) {
            if (declaredField.getName().equals(name)) {
                return declaredField;
            }
        }
        if (type.getSuperclass() != null) {
            return findField(name, type.getSuperclass());
        }
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望,这会对某人有所帮助。