trabajé encontrar una solución con la ayuda de Rohan :)
Adapté su respuesta para adaptarse a mis necesidades.
Cuando el usuario presiona el botón, se inicia una secuencia. El hilo duerme para mi retraso deseado, y cuando se despierta, ejecuta el código que necesito que haga. Cuando el usuario suelta, el hilo se elimina. Esto logra lo que quiero, porque si el usuario lo suelta antes de que el hilo se despierte, el hilo se interrumpe y la acción no se produce.
Me gusta este enfoque porque me permite ejecutar mi lógica de negocio tan pronto como se demora, lo que es bueno porque puedo darle al usuario algunos comentarios haciéndoles saber que han presionado lo suficiente (el teléfono puede vibrar, por ejemplo).
La desventaja de este enfoque es: existe el riesgo de que el usuario suelte el botón mientras se ejecuta la acción deseada, y elimina el hilo antes de que todo esté hecho. Este no es un gran problema para mi caso, porque mi lógica comercial hace muy poco; solo activa un evento para que otra clase lo procese. Si la acción no se completó por completo, es aceptable que el usuario tenga que volver a intentarlo.
El código es un poco más largo de lo que me gustaría, pero si esta es una característica común en su aplicación, es fácilmente reutilizable. Aquí está un ejemplo de código:
protected class MyLongClickListener implements View.OnTouchListener {
private Thread longClickSensor;
public boolean onTouch(View view, MotionEvent event) {
// If the user is pressing down and there is no thread, make one and start it
if (event.getAction() == MotionEvent.ACTION_DOWN && longClickSensor == null) {
longClickSensor = new Thread(new MyDelayedAction());
longClickSensor.start();
}
// If the user has let go and there was a thread, stop it and forget about the thread
if (event.getAction() == MotionEvent.ACTION_UP && longClickSensor != null) {
longClickSensor.interrupt();
longClickSensor = null;
}
return false;
}
private class MyDelayedAction implements Runnable {
private final long delayMs = 1200;
public void run() {
try {
Thread.sleep(delayMs); // Sleep for a while
doBusinessLogic(); // If the thread is still around after the sleep, do the work
} catch (InterruptedException e) { return; }
}
private void doBusinessLogic() {
// Make sure this logic is as quick as possible, or delegate it to some other class
// through Broadcasted Intents, because if the user lets go while the work is happenening,
// the thread will be interrupted.
}
}
}
Esto casi hace lo que necesito hacer. El enfoque publicado solo ejecuta el código cuando el usuario levanta el dedo. Me gustaría que mi lógica de negocios se ejecute tan pronto como se demore, en lugar de cuando el usuario deje de presionar. – ampersandre
¿Por qué se comenta entonces = getSystemTime()? También el método getSystemTime() no funciona. Quiso decir: System.currentTimeMillis() –
Confirmado. Defina entonces como un largo, no como un int. Luego use: then = (Long) System.currentTimeMillis(); y cuando encuentre la diferencia, asegúrese de volver a emitir demasiado cuando use System.currentTimeMillis() en lugar de getSystemTime() –