Cómo eliminar todos los oyentes agregados con addTextChangedListener
Tengo un ListView
donde cada fila tiene un control de EditText
. Quiero agregar un TextChangedListener
a cada fila; Uno que contiene datos adicionales que dice que fila el EditText
estaba EditText
El problema es que como getView
se llama, se agregan múltiples TextWatchers
; Porque el convertView
ya tiene un TextWatcher
(y otro que apunta a una fila diferente).
MyTextWatcher watcher = new MyTextWatcher(currentQuestion); EditText text = (EditText)convertView.findViewById(R.id.responseText); text.addTextChangedListener(watcher);
MyTextWatcher
es mi clase que implementa TextWatcher
; Y maneja los eventos de texto. CurrentQuestion me permite saber a qué fila estoy actuando. Cuando escribo en la caja; Se llaman varias instancias de TextWatcher
.
- Validación de EditText con TextWatcher
- ¿Cómo mostrar "No Result" en ListView filtrable?
- Cómo actualizar el mismo EditText con TextWatcher?
- ¿Cómo usar la clase TextWatcher en Android?
- Formato de la fecha de caducidad en formato mm / aa
¿Hay alguna manera de eliminar el TextWatchers
antes de agregar el nuevo? Veo el método removeTextChangedListener
, pero eso requiere que un TextWatcher
específico sea pasado adentro, y no sé cómo conseguir el puntero al TextWatcher
que está ya allí.
- Android-Editext cambio después de cada cambio
- ¿Cómo utilizo AsYouTypeFormatter TextWatcher en la aplicación de Android?
- TextWatcher para más de un EditText
- Agregar automáticamente guión en el número de teléfono en Android
- Android - Hacer algo * después de * texto se cambia en EditText
- Cómo sólo permitir números positivos en un EditText
- Clickable compuesto drawable en EditText que hace estallar una vista en tecleo
- Cómo enmascarar un EditText para mostrar el formato de fecha dd / mm / aaaa
No hay manera de hacerlo utilizando la interfaz EditText
actual directamente. Veo dos posibles soluciones:
- Rediseñe su aplicación para que siempre sepa qué
TextWatcher
se agrega a la instancia deEditText
particular. - Ampliar
EditText
y añadir la posibilidad de borrar a todos los observadores.
Aquí hay un ejemplo de segundo enfoque: 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; } } }
Y aquí es cómo se puede utilizar ExtendedEditText
en xml layouts:
<?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>
Puede quitar TextWatcher de su EditText. En primer lugar le sugiero que mueva la declaración TextWatcher fuera de la 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 } };
Después de que usted será capaz de configurar TextWather poco más simple:
editText.addTextChangedListener(yourTextWatcher);
Que puede quitar TextWatcher como este:
editText.removeTextChangedListener(yourTextWatcher);
Y establecer otro si lo desea.
También pasé mucho tiempo encontrando la solución y finalmente terminé resolviendo con la ayuda de etiqueta como abajo. Se quitaría anteriores TextWatcher instancias por obtener referencias de la etiqueta de la convertView. Resuelve perfectamente el problema. En su archivo CustomAdapter, establezca una nueva clase interna como la siguiente:
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; } }
A continuación, en su público superpuesto, el método getView (int position, View convertView, ViewGroup parent) implementa la lógica como a continuación:
@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); }
A continuación, implemente la clase TextWatcher como se muestra a continuación:
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"); } }
Se eliminaría instancias anteriores de TextWatcher al obtener referencias de la etiqueta del archivo convertView
Guarde el textwatcher actual en el visor y puede encontrar el que desea eliminar.
Tuve el mismo problema con xamarin / C # y escribí para esto una clase para administrar eventos de clic dentro de un ListView donde la vista del elemento será "reciclado":
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; } }
Puede utilizarlo en su método ListView BaseAdapter GetItem de esta manera:
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 }));
La clase ViewOnClickEventHandler se preocupará por varios eventos en su texto. También puede cambiar la clase para los eventos de intercambio de texto. Es el mismo principio. Espero que esto sea de ayuda.
Bye, nxexo007
Como se puede ver aquí: CodeSearch de TextView no hay manera de eliminar todos los oyentes. La única manera es proporcionar al vigilante que usted utilizó para registrarlo.
Todavía no entiendo por qué hay otros oyentes ya registrados. Sin embargo, puede subclasificar el EditText, anular el addTextChangedListener (..) y en él mantener una copia de todas las referencias añadidas a ti mismo y luego delegar a la implementación de superclase. A continuación, también puede proporcionar un método adicional que elimina todos los oyentes.
Ponte en contacto si necesitas más explicaciones.
Lo que hice para eliminar los observadores de texto es muy simple. He creado una matriz para poner mis textwatchers:
final TextWatcher[] textWatchers = new TextWatcher[3];
Los agregué en:
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);
Mi método returnTextWatcherCheckPIN crea una instancia de textWatcher con un comprobador diferente (switchMethod para comprobar los cuatro editTexts) en afterTextChanged.
Entonces cada vez que quito un observador del texto apenas he referido el uno de la matriz:
etPin4.removeTextChangedListener(textWatchers[CURRENT_PIN_CHECK]);
Compruebe el tamaño de los oyentes del editText en depuración:
¡Se ha eliminado! Eso resolvió mi problema!