Quiero capturar un evento cuando el usuario termine de editar EditText.
¿Cómo puede hacerse esto?
override fun afterTextChanged(s: Editable?) { if (s.toString().length == 5) { val enteredString = s.toString() }
Quiero capturar un evento cuando el usuario termine de editar EditText.
¿Cómo puede hacerse esto?
override fun afterTextChanged(s: Editable?) { if (s.toString().length == 5) { val enteredString = s.toString() }
Respuestas:
Cuando el usuario haya terminado de editar, presionará Done
oEnter
((EditText)findViewById(R.id.youredittext)).setOnEditorActionListener(
new EditText.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH ||
actionId == EditorInfo.IME_ACTION_DONE ||
event != null &&
event.getAction() == KeyEvent.ACTION_DOWN &&
event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
if (event == null || !event.isShiftPressed()) {
// the user is done typing.
return true; // consume.
}
}
return false; // pass on to other listeners.
}
}
);
Mejor manera, también puede usar EditText en el oyente FocusChange para verificar si el usuario ha realizado la edición: (No es necesario que el usuario presione el botón Listo o Enter en el teclado en pantalla)
((EditText)findViewById(R.id.youredittext)).setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
// When focus is lost check that the text field has valid values.
if (!hasFocus) { {
// Validate youredittext
}
}
});
Nota: Para más de un EditText, también puede permitir que su clase implemente, View.OnFocusChangeListener
luego configure los oyentes para cada uno de ustedes EditText y validelos como se muestra a continuación.
((EditText)findViewById(R.id.edittext1)).setOnFocusChangeListener(this);
((EditText)findViewById(R.id.edittext2)).setOnFocusChangeListener(this);
@Override
public void onFocusChange(View v, boolean hasFocus) {
// When focus is lost check that the text field has valid values.
if (!hasFocus) {
switch (view.getId()) {
case R.id.edittext1:
// Validate EditText1
break;
case R.id.edittext2:
// Validate EditText2
break;
}
}
}
EditText
. Nunca perderá el enfoque.
EditText
? ¿Tengo que usar onEditorAction
?
EditText
, valida lo que haga el usuario para salir de la pantalla.
W/ViewRootImpl: Cancelling event due to no window focus: MotionEvent { action=ACTION_CANCEL, actionButton=0, id[0]=0, x[0]=605.52246, y[0]=969.4336, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=238238, downTime=235422, deviceId=0, source=0x1002 }
Aunque escribí algo. Este es un texto de edición que solo acepta números.
Personalmente, prefiero el envío automático después de finalizar la escritura. Así es como puede detectar este evento.
Declaraciones e inicialización:
private Timer timer = new Timer();
private final long DELAY = 1000; // in ms
Oyente en, por ejemplo, onCreate ()
EditText editTextStop = (EditText) findViewById(R.id.editTextStopId);
editTextStop.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void onTextChanged(final CharSequence s, int start, int before,
int count) {
if(timer != null)
timer.cancel();
}
@Override
public void afterTextChanged(final Editable s) {
//avoid triggering event when text is too short
if (s.length() >= 3) {
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
// TODO: do what you need here (refresh list)
// you will probably need to use
// runOnUiThread(Runnable action) for some specific
// actions
serviceConnector.getStopPoints(s.toString());
}
}, DELAY);
}
}
});
Entonces, cuando se cambia el texto, el temporizador comienza a esperar a que ocurran los próximos cambios. Cuando ocurren, el temporizador se cancela y luego se inicia una vez más.
Handler
lugar
Puedes hacerlo usando setOnKeyListener o usando un textWatcher como:
Establecer observador de texto editText.addTextChangedListener(textWatcher);
luego llame
private TextWatcher textWatcher = new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
//after text changed
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
};
Aunque muchas respuestas apuntan en la dirección correcta, creo que ninguna de ellas responde a lo que estaba pensando el autor de la pregunta. O al menos entendí la pregunta de manera diferente porque estaba buscando una respuesta a un problema similar. El problema es "Cómo saber cuándo el usuario deja de escribir sin que él presione un botón" y desencadenar alguna acción (por ejemplo, autocompletar). Si desea hacer esto, inicie el temporizador en onTextChanged con un retraso que consideraría que el usuario dejó de escribir (por ejemplo, 500-700ms), para cada nueva letra cuando inicie el temporizador, cancele la anterior (o al menos use algún tipo de marcar que cuando marcan no hacen nada). Aquí hay un código similar al que he usado:
new Timer().schedule(new TimerTask() {
@Override
public void run() {
if (!running) {
new DoPost().execute(s.toString());
});
}
}, 700);
Tenga en cuenta que modifico el indicador booleano en ejecución dentro de mi tarea asíncrona (Task obtiene el json del servidor para autocompletar).
También tenga en cuenta que esto crea muchas tareas de temporizador (creo que están programadas en el mismo hilo, pero tendría que verificar esto), por lo que probablemente haya muchos lugares para mejorar, pero este enfoque también funciona y la conclusión es que debería usar un temporizador ya que no hay ningún evento "El usuario dejó de escribir"
tanto @Reno como @Vinayak B responden juntos si quieren ocultar el teclado después de la acción
textView.setOnEditorActionListener(new EditText.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_ACTION_DONE) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(textView.getWindowToken(), 0);
return true;
}
return false;
}
});
textView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
// your action here
}
}
});
Un enfoque diferente ... aquí hay un ejemplo: si el usuario tiene un retraso de 600-1000ms cuando está escribiendo, puede considerar que está detenido.
myEditText.addTextChangedListener(new TextWatcher() {
private String s;
private long after;
private Thread t;
private Runnable runnable_EditTextWatcher = new Runnable() {
@Override
public void run() {
while (true) {
if ((System.currentTimeMillis() - after) > 600)
{
Log.d("Debug_EditTEXT_watcher", "(System.currentTimeMillis()-after)>600 -> " + (System.currentTimeMillis() - after) + " > " + s);
// Do your stuff
t = null;
break;
}
}
}
};
@Override
public void onTextChanged(CharSequence ss, int start, int before, int count) {
s = ss.toString();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable ss) {
after = System.currentTimeMillis();
if (t == null)
{
t = new Thread(runnable_EditTextWatcher);
t.start();
}
}
});
Bien, esto funcionará al 100% seguro.
Primero deberá configurar el oyente si el teclado se muestra u oculta. Si se muestra el teclado, probablemente el usuario esté escribiendo; de lo contrario, termine de escribir.
final View activityRootView = findViewById(android.R.id.content);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect r = new Rect();
//r will be populated with the coordinates of your view that area still visible.
activityRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
isTyping = true;
} else {
//to make sure this will call only once when keyboard is hide.
if(isTyping){
isTyping = false;
}
}
}
});
heightDiff > 100
cosas dan miedo en mi humilde opinión.
Resolví este problema de esta manera. Usé kotlin.
var timer = Timer()
var DELAY:Long = 2000
editText.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
Log.e("TAG","timer start")
timer = Timer()
timer.schedule(object : TimerTask() {
override fun run() {
//do something
}
}, DELAY)
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
Log.e("TAG","timer cancel ")
timer.cancel() //Terminates this timer,discarding any currently scheduled tasks.
timer.purge() //Removes all cancelled tasks from this timer's task queue.
}
})
Tuve el mismo problema y no quería depender de que el usuario presionara Listo o Enter.
Mi primer intento fue usar el oyente onFocusChange, pero ocurrió que mi EditText obtuvo el foco de forma predeterminada. Cuando el usuario presionaba alguna otra vista, onFocusChange se activaba sin que el usuario le hubiera asignado el foco.
La siguiente solución lo hizo por mí, donde onFocusChange se adjunta si el usuario toca EditText:
final myEditText = new EditText(myContext); //make final to refer in onTouch
myEditText.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
myEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(!hasFocus){
// user is done editing
}
}
}
}
}
En mi caso, cuando el usuario terminó de editar la pantalla se volvió a renderizar, renovando así el objeto myEditText. Si se mantiene el mismo objeto, probablemente debería eliminar el oyente onFocusChange en onFocusChange para evitar el problema onFocusChange descrito al comienzo de esta publicación.
Tuve el mismo problema al intentar implementar "ahora escribiendo" en la aplicación de chat. intente extender EditText de la siguiente manera:
public class TypingEditText extends EditText implements TextWatcher {
private static final int TypingInterval = 2000;
public interface OnTypingChanged {
public void onTyping(EditText view, boolean isTyping);
}
private OnTypingChanged t;
private Handler handler;
{
handler = new Handler();
}
public TypingEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.addTextChangedListener(this);
}
public TypingEditText(Context context, AttributeSet attrs) {
super(context, attrs);
this.addTextChangedListener(this);
}
public TypingEditText(Context context) {
super(context);
this.addTextChangedListener(this);
}
public void setOnTypingChanged(OnTypingChanged t) {
this.t = t;
}
@Override
public void afterTextChanged(Editable s) {
if(t != null){
t.onTyping(this, true);
handler.removeCallbacks(notifier);
handler.postDelayed(notifier, TypingInterval);
}
}
private Runnable notifier = new Runnable() {
@Override
public void run() {
if(t != null)
t.onTyping(TypingEditText.this, false);
}
};
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
@Override
public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { }
}
Terminé con ella con el mismo problema y no pude usar la solución con onEditorAction o onFocusChange y no quería probar el temporizador. Un temporizador es demasiado peligroso para su gusto, debido a todos los hilos y demasiado impredecible, ya que no sabe cuándo se ejecuta el código.
El onEditorAction no detecta cuando el usuario se va sin usar un botón y, si lo usa, tenga en cuenta que KeyEvent puede ser nulo. El enfoque no es confiable en ambos extremos, el usuario puede enfocarse y salir sin ingresar ningún texto o seleccionar el campo y el usuario no necesita salir del último campo EditText.
Mi solución usa onFocusChange y una bandera establecida cuando el usuario comienza a editar texto y una función para obtener el texto de la última vista enfocada, a la que llamo cuando lo necesito.
Simplemente borro el foco en todos mis campos de texto para engañar el código de vista de texto de salida. El código clearFocus solo se ejecuta si el campo tiene el foco. Llamo a la función en onSaveInstanceState para no tener que guardar la bandera (mEditing) como un estado de la vista EditText y cuando se hace clic en botones importantes y cuando se cierra la actividad.
Tenga cuidado con TexWatcher, ya que es una llamada que a menudo uso la condición en el foco para no reaccionar cuando el código onRestoreInstanceState ingresa texto. yo
final EditText mEditTextView = (EditText) getView();
mEditTextView.addTextChangedListener(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) {
if (!mEditing && mEditTextView.hasFocus()) {
mEditing = true;
}
}
});
mEditTextView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus && mEditing) {
mEditing = false;
///Do the thing
}
}
});
protected void saveLastOpenField(){
for (EditText view:getFields()){
view.clearFocus();
}
}
He hecho algo como esta clase abstracta que se puede usar en lugar del tipo TextView.OnEditorActionListener.
abstract class OnTextEndEditingListener : TextView.OnEditorActionListener {
override fun onEditorAction(textView: TextView?, actionId: Int, event: KeyEvent?): Boolean {
if(actionId == EditorInfo.IME_ACTION_SEARCH ||
actionId == EditorInfo.IME_ACTION_DONE ||
actionId == EditorInfo.IME_ACTION_NEXT ||
event != null &&
event.action == KeyEvent.ACTION_DOWN &&
event.keyCode == KeyEvent.KEYCODE_ENTER) {
if(event == null || !event.isShiftPressed) {
// the user is done typing.
return onTextEndEditing(textView, actionId, event)
}
}
return false // pass on to other listeners
}
abstract fun onTextEndEditing(textView: TextView?, actionId: Int, event: KeyEvent?) : Boolean
}
Fácil de activar, termine de escribir en EditText
funcionó para mí, si usa java, conviértalo
En Kotlin
youredittext.doAfterTextChanged { searchTerm ->
val currentTextLength = searchTerm?.length
Handler().postDelayed({
if (currentTextLength == searchTerm?.length) {
// your code
Log.d("aftertextchange", "ON FINISH TRIGGER")
}
}, 3000)
}