escucha de Cambios de Texto en Android


Tengo una situación, donde hay dos campos. field1 y field2. Todo lo que quiero hacer está vacío field2 cuando se cambia field1 y viceversa. Así que 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 se bloquea. Obviamente porque tratan de cambiar indefinidamente. Una vez que field1 cambia, borra field2 en este momento field2 se cambia para que se aclare field1 y así sucesivamente...

Puede alguien sugerir alguna solución?

Author: mariotomo, 2013-12-29

7 answers

Puede agregar una comprobación para borrar solo cuando el texto en el campo no está vacío (es decir, cuando la longitud es 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 por favor respete las convenciones de nomenclatura.

 317
Author: user2336315,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-24 15:17:41

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 un EditText y onTextChanged sería llamado cuando no quería que lo hiciera. Mi primera solución fue escribir un poco de 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 usando getText ().clear() borra el texto de la misma manera que setText (""), pero ya que no está configurando el texto al oyente no se le llama, así que eso 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();
   }
  });
 10
Author: BobVicktor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-16 02:38:19

Un poco tarde en 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);
}

Así que cuando se usa lo anterior, cualquier llamada setText() que ocurra dentro del TextWatcher no resultará en que el TextWatcher sea llamado de nuevo:

/**
 * 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) {
    }
}
 4
Author: Eurig Jones,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-15 10:24:14

Compruebe la cadena antes de establecer otro EditText en vacío. si Field1 está vacío, ¿por qué necesita cambiar de nuevo a ("")? así que puedes comprobar el tamaño de Tu Cadena con s. lenght () o cualquier otra solución

Otra forma de comprobar la longitud de la cadena es:

String sUsername = Field1.getText().toString();
if (!sUsername.matches(""))
{
// do your job
}
 3
Author: Shayan Pourvatan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-29 11:28:23

También me he enfrentado al mismo problema y sigo obteniendo excepciones completas de pila, 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 boolean skipOnChange = false;

 3
Author: Sumit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-14 07:59:37

Si estás usando Kotlin para el desarrollo de Android, puedes agregar el listener de cambios 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) {}
    })
 2
Author: iHulk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-25 07:04:55

También puedes 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 escalas de temperatura a medida que el usuario las escribía. Funcionó perfectamente, y es mucho más simple.

 1
Author: renam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-10 03:58:49