Как удалить всех слушателей, добавленных с помощью addTextChangedListener

У меня есть ListView где каждая строка имеет элемент управления EditText . Я хочу добавить TextChangedListener в каждую строку; getView содержит дополнительные данные, в которых указывается, в какой строке находится EditText . Проблема в том, что при getView TextWatchers добавляется несколько TextWatchers ; Потому что convertView уже имеет TextWatcher (и тот, который указывает на другую строку).

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

MyTextWatcher – мой класс, который реализует TextWatcher ; И обрабатывает текстовые события. CurrentQuestion позволяет мне узнать, в какой строке я действую. Когда я ввожу в поле; TextWatcher несколько экземпляров TextWatcher .

Есть ли способ удалить TextWatchers перед добавлением нового? Я вижу метод removeTextChangedListener , но для этого требуется, чтобы определенный TextWatcher был передан, и я не знаю, как получить указатель на TextWatcher который уже существует.

Это невозможно сделать с помощью текущего интерфейса 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; } } } 

И вот как вы можете использовать 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> 

Вы можете удалить TextWatcher из вашего EditText. Прежде всего, я предлагаю вам переместить объявление 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); 

И установите другой, если хотите.

Я также потратил много времени на поиск решения и, наконец, решил решить с помощью тега, как показано ниже. Он удаляет предыдущие экземпляры TextWatcher, получая ссылки из тега convertView. Это прекрасно решает проблему. В вашем файле 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; } } 

Затем в вашем переопределенном общедоступном представлении 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"); } } 

Он удаляет предыдущие экземпляры TextWatcher, получая ссылки из тега convertView

Сохраните текущий текстовый элемент в представлении, и вы можете найти тот, который хотите удалить.

У меня была такая же проблема с xamarin / C #, и я написал для этого класс, чтобы управлять событиями click внутри 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; } } 

Вы можете использовать его в методе GetView ListAdapter BaseAdapter следующим образом:

  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. Это тот же принцип. Я надеюсь, это поможет.

Bye, nxexo007

Как вы можете видеть здесь: CodeSearch TextView не удаляет всех слушателей. Единственный способ – предоставить наблюдателю, который вы использовали для его регистрации.

Я еще не понял, почему другие слушатели уже зарегистрированы. Однако вы можете подклассифицировать EditText, переопределить addTextChangedListener (..) и в нем самостоятельно хранить копию всех добавленных ссылок, а затем делегировать реализацию суперкласса. Затем вы также можете предоставить дополнительный метод, который удаляет всех слушателей.

Свяжитесь с нами, если вам нужны дополнительные объяснения.

То, что я сделал для удаления текстовых наблюдателей, очень просто. Я создал массив для размещения моих текстовых элементов:

 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 создает экземпляр textWatcher с другой проверкой (switchMethod для проверки всех четырех editTexts) на afterTextChanged.

Затем, когда я удаляю текстовый наблюдатель, я просто ссылался на один из массива:

 etPin4.removeTextChangedListener(textWatchers[CURRENT_PIN_CHECK]); 

Проверьте размер прослушивателя editText при отладке:

Введите описание изображения здесь

Он удален! Это решило мою проблему!

Intereting Posts
Ошибка неправильной версии хранилища ключей. Как создать сертификат = 1 кейстор? Новичкам для мобильных разработчиков (Android и iOS) необходимо руководствоваться Получить цвет фона кнопки в android Истекает ли идентификатор регистрации GCM? Сделать полосы прокрутки из кода (например, iOS flashScrollIndicators) Обновление списка просмотра Android Расширенные протоколы Wi-Fi в Android L Developer Options Как обрабатывать все TouchEvents на уровне ViewGroup (т. Е. Bubble все события вплоть до группы viewgroup) Разрешить только число и период (.) В тексте редактирования в android Ошибка Android Auth: «GetToken не удалось с кодом состояния: INVALID_AUDIENCE» Как добавить кнопку в конце RecyclerView? Как настроить ошибку Служб Google Play на Android Прекратить синхронизацию Android SyncAdapter Android – Сохранение / извлечение строк с использованием общих настроек Android сокращают пространство между двумя вертикальными TextViews