android on Text Change Listener

Tengo una situación, donde hay dos campos. field2 y field2 . Todo lo que quiero hacer es vaciar el field2 cuando se cambia el field2 y viceversa. Entonces, al final, solo un campo tiene contenido.

 field1 = (EditText)findViewById(R.id.field1); field2 = (EditText)findViewById(R.id.field2); field1.addTextChangedListener(new TextWatcher() { public void afterTextChanged(Editable s) {} public void beforeTextChanged(CharSequence s, int start, int count, int after) { } public void onTextChanged(CharSequence s, int start, int before, int count) { field2.setText(""); } }); field2.addTextChangedListener(new TextWatcher() { public void afterTextChanged(Editable s) {} public void beforeTextChanged(CharSequence s, int start, int count, int after) { } public void onTextChanged(CharSequence s, int start, int before, int count) { field1.setText(""); } }); 

Funciona bien si adjunto addTextChangedListener a field1 solamente, pero cuando lo hago para ambos campos, la aplicación falla. Obviamente, porque intentan cambiarse indefinidamente. Una vez que el field2 cambia, borra el field2 en este momento el field2 se cambia por lo que borrará el field1 y así sucesivamente …

¿Alguien puede sugerir alguna solución?

Puede agregar una verificación para borrar solo cuando el texto en el campo no esté vacío (es decir, cuando la longitud sea diferente de 0).

 field1.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable s) {} @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if(s.length() != 0) field2.setText(""); } }); field2.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable s) {} @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if(s.length() != 0) field1.setText(""); } }); 

Documentación para TextWatcher aquí .

También respete las convenciones de nombres .

Sé que esto es viejo, pero alguien podría encontrarse con esto de nuevo algún día.

Tuve un problema similar en el que llamaría a setText en EditText y onTextChanged se llamaría cuando yo no quisiera. Mi primera solución fue escribir un código después de llamar a setText () para deshacer el daño hecho por el oyente. Pero eso no fue muy elegante. Después de hacer algunas investigaciones y pruebas, descubrí que el uso de getText (). Clear () borra el texto casi de la misma manera que setText (“”), pero como no está configurando el texto, no se llama al oyente, por lo que resolvió mi problema Cambié todas mis llamadas setText (“”) a getText (). Clear () y ya no necesitaba las vendas, así que tal vez eso también solucione tu problema.

Prueba esto:

 Field1 = (EditText)findViewById(R.id.field1); Field2 = (EditText)findViewById(R.id.field2); Field1.addTextChangedListener(new TextWatcher() { public void afterTextChanged(Editable s) {} public void beforeTextChanged(CharSequence s, int start, int count, int after) { } public void onTextChanged(CharSequence s, int start, int before, int count) { Field2.getText().clear(); } }); Field2.addTextChangedListener(new TextWatcher() { public void afterTextChanged(Editable s) {} public void beforeTextChanged(CharSequence s, int start, int count, int after) { } public void onTextChanged(CharSequence s, int start, int before, int count) { Field1.getText().clear(); } }); 

Un poco tarde de una respuesta, pero aquí hay una solución reutilizable:

 /** * An extension of TextWatcher which stops further callbacks being called as * a result of a change happening within the callbacks themselves. */ public abstract class EditableTextWatcher implements TextWatcher { private boolean editing; @Override public final void beforeTextChanged(CharSequence s, int start, int count, int after) { if (editing) return; editing = true; try { beforeTextChange(s, start, count, after); } finally { editing = false; } } protected abstract void beforeTextChange(CharSequence s, int start, int count, int after); @Override public final void onTextChanged(CharSequence s, int start, int before, int count) { if (editing) return; editing = true; try { onTextChange(s, start, before, count); } finally { editing = false; } } protected abstract void onTextChange(CharSequence s, int start, int before, int count); @Override public final void afterTextChanged(Editable s) { if (editing) return; editing = true; try { afterTextChange(s); } finally { editing = false; } } public boolean isEditing() { return editing; } protected abstract void afterTextChange(Editable s); } 

Entonces, cuando se usa lo anterior, cualquier setText() ocurra dentro del TextWatcher no provocará que se llame de nuevo al TextWatcher:

 /** * A setText() call in any of the callbacks below will not result in TextWatcher being * called again. */ public class MyTextWatcher extends EditableTextWatcher { @Override protected void beforeTextChange(CharSequence s, int start, int count, int after) { } @Override protected void onTextChange(CharSequence s, int start, int before, int count) { } @Override protected void afterTextChange(Editable s) { } } 

marque String antes de configurar otro EditText para vaciar. si Field1 está vacío, ¿por qué hay que volver a cambiar a (“”)? para que pueda verificar el tamaño de su cadena con s.lenght () o cualquier otra solución

Otra forma de verificar la longitud de String es:

 String sUsername = Field1.getText().toString(); if (!sUsername.matches("")) { // do your job } 

También me he enfrentado al mismo problema y continúo obteniendo excepciones de stack completa, y vengo con la siguiente solución.

  edt_amnt_sent.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable s) { if (skipOnChange) return; skipOnChange = true; try { //method } } catch (NumberFormatException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { skipOnChange = false; } } }); edt_amnt_receive.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable s) { if (skipOnChange) return; skipOnChange = true; try { //method } catch (NumberFormatException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { skipOnChange = false; } } }); 

declarado inicialmente booleano skipOnChange = false;

También puede usar el método hasFocus ():

 public void onTextChanged(CharSequence s, int start, int before, int count) { if (Field2.hasfocus()){ Field1.setText(""); } } 

Probé esto para una tarea universitaria en la que estaba trabajando para convertir las escalas de temperatura a medida que el usuario las ingresaba. Funcionó perfectamente, y es mucho más simple.

Si está utilizando Kotlin para el desarrollo de Android, puede agregar el oyente de cambio de texto usando este código:

 myTextField.addTextChangedListener(object : TextWatcher{ override fun afterTextChanged(s: Editable?) {} override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {} })