Как удалить всех слушателей, добавленных с помощью addTextChangedListener
У меня есть ListView
, где каждая строка имеет элемент управления EditText
. Я хочу добавить TextChangedListener
в каждую строку; который содержит дополнительные данные, в которых указывается, какая строка была EditText
. Проблема заключается в том, что при вызове getView
вызывается несколько TextWatchers
; потому что convertView
уже имеет TextWatcher
(и тот, который указывает на другую строку).
MyTextWatcher watcher = new MyTextWatcher(currentQuestion);
EditText text = (EditText)convertView.findViewById(R.id.responseText);
text.addTextChangedListener(watcher);
MyTextWatcher
- это мой класс, который реализует TextWatcher
; и обрабатывает текстовые события. CurrentQuestion позволяет мне узнать, в какой строке я действую. Когда я ввожу в поле; вызывается несколько экземпляров TextWatcher
.
Есть ли способ удалить TextWatchers
перед добавлением нового? Я вижу метод removeTextChangedListener
, но для этого требуется конкретный TextWatcher
, и я не знаю, как получить указатель на TextWatcher
, который уже существует.
Ответы
Ответ 1
Невозможно сделать это с помощью текущего интерфейса EditText
. Я вижу два возможных решения:
- Перепроектируйте ваше приложение, чтобы вы всегда знали, что
TextWatcher
добавлено в конкретный экземпляр EditText
.
- Расширьте
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>
Ответ 2
Вы можете удалить 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);
и установите другое, если хотите.
Ответ 3
Я также потратил много времени на поиск решения и, наконец, решил решить с помощью тега, как показано ниже.
Он удаляет предыдущие экземпляры 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
Ответ 4
Сохраните текущий текстовый элемент в узле просмотра, и вы можете найти тот, который хотите удалить.
Ответ 5
У меня была такая же проблема с xamarin/С#, и я написал для этого класс для управления событиями 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. Это тот же принцип.
Надеюсь, это поможет.
До свидания,
nxexo007
Ответ 6
Я решил эту ситуацию без расширения класса 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();
}
Ответ 7
Как вы можете видеть здесь: CodeSearch TextView, нет способа удалить всех слушателей. Единственный способ - предоставить наблюдателю, который вы использовали для его регистрации.
Я еще не совсем понял, почему другие слушатели уже зарегистрированы. Однако вы можете подклассифицировать EditText, переопределить addTextChangedListener (..) и в нем сохранить копию всех добавленных ссылок самостоятельно, а затем делегировать реализацию суперкласса. Затем вы также можете предоставить дополнительный метод, который удаляет всех слушателей.
Обратитесь к нам, если вам нужны дополнительные пояснения.
Ответ 8
То, что я сделал для удаления текстовых наблюдателей, очень просто. Я создал массив для размещения моих текстовых элементов:
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 при отладке:
![введите описание изображения здесь]()
Удалено! Это решило мою проблему!
Ответ 9
Я боролся с подобной проблемой. Я решил это, сохранив ссылки на мои textWatchers в ArrayList
:
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));
}