La TextWatcher
interfaz tiene 3 métodos de devolución de llamada que se llaman en el siguiente orden cuando se produce un cambio en el texto:
beforeTextChanged(CharSequence s, int start, int count, int after)
Se llama antes de que los cambios se hayan aplicado al texto.
El s
parámetro es el texto antes de que se aplique cualquier cambio.
El start
parámetro es la posición del comienzo de la parte modificada en el texto.
El count
parámetro es la longitud de la parte cambiada en la s
secuencia desde la start
posición.
Y el after
parámetro es la longitud de la nueva secuencia que reemplazará la parte de la s
secuencia de start
a start+count
.
No debe cambiar el texto en el TextView
de este método (usando myTextView.setText(String newText)
).
onTextChanged(CharSequence s, int start, int before, int count)
Similar al beforeTextChanged
método pero llamado después de que cambia el texto.
El s
parámetro es el texto después de que se hayan aplicado los cambios.
El start
parámetro es el mismo que en el beforeTextChanged
método.
El count
parámetro es el after
parámetro del método beforeTextChanged.
Y el before
parámetro es el count
parámetro en el método beforeTextChanged.
No debe cambiar el texto en el TextView
de este método (usando myTextView.setText(String newText)
).
afterTextChanged(Editable s)
Puede cambiar el texto TextView
de este método.
/! \ Advertencia: Cuando cambie el texto en TextView
, el TextWatcher
se activará nuevamente, iniciando un ciclo infinito. Luego debe agregar una boolean _ignore
propiedad similar que evite el bucle infinito.
Ejemplo:
new TextWatcher() {
boolean _ignore = false; // indicates if the change was made by the TextWatcher itself.
@Override
public void afterTextChanged(Editable s) {
if (_ignore)
return;
_ignore = true; // prevent infinite loop
// Change your text here.
// myTextView.setText(myNewText);
_ignore = false; // release, so the TextWatcher start to listen again.
}
// Other methods...
}
Resumen:
Una clase lista para usar: TextViewListener
Personalmente, hice mi oyente de texto personalizado, que me da las 4 partes en cadenas separadas, lo cual es, para mí, mucho más intuitivo de usar.
/**
* Text view listener which splits the update text event in four parts:
* <ul>
* <li>The text placed <b>before</b> the updated part.</li>
* <li>The <b>old</b> text in the updated part.</li>
* <li>The <b>new</b> text in the updated part.</li>
* <li>The text placed <b>after</b> the updated part.</li>
* </ul>
* Created by Jeremy B.
*/
public abstract class TextViewListener implements TextWatcher {
/**
* Unchanged sequence which is placed before the updated sequence.
*/
private String _before;
/**
* Updated sequence before the update.
*/
private String _old;
/**
* Updated sequence after the update.
*/
private String _new;
/**
* Unchanged sequence which is placed after the updated sequence.
*/
private String _after;
/**
* Indicates when changes are made from within the listener, should be omitted.
*/
private boolean _ignore = false;
@Override
public void beforeTextChanged(CharSequence sequence, int start, int count, int after) {
_before = sequence.subSequence(0,start).toString();
_old = sequence.subSequence(start, start+count).toString();
_after = sequence.subSequence(start+count, sequence.length()).toString();
}
@Override
public void onTextChanged(CharSequence sequence, int start, int before, int count) {
_new = sequence.subSequence(start, start+count).toString();
}
@Override
public void afterTextChanged(Editable sequence) {
if (_ignore)
return;
onTextChanged(_before, _old, _new, _after);
}
/**
* Triggered method when the text in the text view has changed.
* <br/>
* You can apply changes to the text view from this method
* with the condition to call {@link #startUpdates()} before any update,
* and to call {@link #endUpdates()} after them.
*
* @param before Unchanged part of the text placed before the updated part.
* @param old Old updated part of the text.
* @param aNew New updated part of the text?
* @param after Unchanged part of the text placed after the updated part.
*/
protected abstract void onTextChanged(String before, String old, String aNew, String after);
/**
* Call this method when you start to update the text view, so it stops listening to it and then prevent an infinite loop.
* @see #endUpdates()
*/
protected void startUpdates(){
_ignore = true;
}
/**
* Call this method when you finished to update the text view in order to restart to listen to it.
* @see #startUpdates()
*/
protected void endUpdates(){
_ignore = false;
}
}
Ejemplo:
myEditText.addTextChangedListener(new TextViewListener() {
@Override
protected void onTextChanged(String before, String old, String aNew, String after) {
// intuitive usation of parametters
String completeOldText = before + old + after;
String completeNewText = before + aNew + after;
// update TextView
startUpdates(); // to prevent infinite loop.
myEditText.setText(myNewText);
endUpdates();
}
}