tutorial theme studio notification example drop custom component and android event-handling

android - theme - El evento LongClick sucede demasiado rápido. ¿Cómo puedo aumentar el tiempo de clic requerido para activarlo?



notification example android (6)

Encontré una solución simple estudiando cómo funciona el evento de prensa larga. Cada vez que se hace clic en una vista, un Runnable de tipo CheckForLongPress se agrega a una cola con un retraso. Si el retraso finaliza, se llama a OnLongClickListener . Si hay un evento diferente antes de que finalice el retraso, entonces, CheckForLongPress Runnable se elimina de la cola.

Acabo de anular el método público postDelayed(Runnable action, long delayMillis) de la vista para cambiar el retardo del sistema operativo

@Override public boolean postDelayed(Runnable action, long delayMillis) { boolean isLongPress = action.getClass().getSimpleName().equals("CheckForLongPress"); return super.postDelayed(action, isLongPress ? LONG_PRESS_MILLIS : delayMillis); }

Puse LONG_PRESS_MILLIS en 100 y está funcionando!

¡¡¡Espero eso ayude!!! ;)

En una aplicación en la que estoy trabajando, tengo el requisito de que un usuario debe hacer clic y mantener presionado un componente durante un período de tiempo antes de que ocurra una determinada acción.

Actualmente estoy usando un OnLongClickListener para escuchar el clic largo, pero encuentro que la duración de un clic para activar el evento OnLongClick es demasiado corta.

Por ejemplo, digamos que los eventos LongClick se activan después de un clic de 400 ms, pero quiero que el usuario tenga que hacer clic y mantener durante 1200 ms antes de los eventos.

¿Hay alguna manera de que pueda configurar el evento LongClick para requerir un clic más largo?
¿O quizás hay otra construcción que me permita escuchar clics más largos?


Esta es la forma más sencilla que he encontrado para lograr este comportamiento. Tiene un par de ventajas sobre la respuesta actualmente aceptada.

  1. Al marcar view.isPressed nos aseguramos de que onClick y onLongClick no se onLongClick si el evento táctil abandona la vista. Esto imita el comportamiento predeterminado del sistema onClick y onLongClick .
  2. El evento ya almacena información de tiempo, por lo que no es necesario almacenar la hora de inicio en ACTION_DOWN o calcular la hora actual en ACTION_UP nosotros mismos. Esto significa que podemos usarlo para múltiples vistas al mismo tiempo porque no estamos rastreando la hora de inicio del evento en una sola variable fuera de onTouch .

NOTA: ViewConfiguration.getLongPressTimeout() es el valor predeterminado y puede cambiar esa comprobación para usar el valor que desee.

NOTA: si normalmente no se puede hacer clic en la vista, deberá llamar a view.setClickable(true) para que la view.isPressed() funcione.

@Override public boolean onTouch(View view, MotionEvent event) { if (view.isPressed() && event.getAction() == MotionEvent.ACTION_UP) { long eventDuration = event.getEventTime() - event.getDownTime(); if (eventDuration > ViewConfiguration.getLongPressTimeout()) { onLongClick(view); } else { onClick(view); } } return false; }

Si, como @ampersandre, desea que el evento de clic prolongado se dispare inmediatamente una vez que se alcance el período de demora en lugar de esperar a ACTION_UP entonces lo siguiente funciona bien para mí.

@Override public boolean onTouch(View view, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { view.setTag(true); } else if (view.isPressed() && (boolean) view.getTag()) { long eventDuration = event.getEventTime() - event.getDownTime(); if (eventDuration > ViewConfiguration.getLongPressTimeout()) { view.setTag(false); onLongClick(view); } else if (event.getAction() == MotionEvent.ACTION_UP) { onClick(view); } } return false; }


No es posible cambiar el temporizador en el evento onLongClick, es administrado por el propio Android.

Lo que es posible es usar .setOnTouchListener ().

Luego regístrate cuando el MotionEvent es un ACTION_DOWN.
Anote la hora actual en una variable.
Luego, cuando se registra un MotionEvent con ACTION_UP y el current_time - actionDown time> 1200 ms, haga algo.

tan bastante

Button button = new Button(); long then = 0; button.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if(event.getAction() == MotionEvent.ACTION_DOWN){ then = (Long) System.currentTimeMillis(); } else if(event.getAction() == MotionEvent.ACTION_UP){ if(((Long) System.currentTimeMillis() - then) > 1200){ return true; } } return false; } })


Trabajé una solución con la ayuda de :)
Adapté su respuesta para que se ajustara a mis necesidades.

Cuando el usuario presiona el botón, se inicia un hilo. El hilo duerme para mi retraso deseado, luego, cuando se despierta, ejecuta el código que necesito que haga. Cuando el usuario deja ir, el hilo se mata. Esto logra lo que quiero, porque si el usuario se retira 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 negocios tan pronto como se retrasa la demora, lo que es bueno porque puedo proporcionarle al usuario algunos comentarios que le permitan saber que han presionado el tiempo 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 mata el hilo antes de que todo se haga. Este no es un gran problema para mi caso, porque mi lógica de negocios hace muy poco; simplemente dispara un evento para que otra clase lo procese. Si la acción no se completó completamente, 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í hay 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. } } }


Un método puede hacerlo. Es fácil de usar, fácil de configurar el tiempo, a tiempo para activar la devolución de llamada.

public static void setOnLongClickListener(final View view, final View.OnLongClickListener longClickListener, final long delayMillis) { view.setOnTouchListener(new View.OnTouchListener() { final Handler handler = new Handler(); final Runnable runnable = new Runnable() { @Override public void run() { longClickListener.onLongClick(view); mRunning = false; } }; boolean mRunning; boolean mOutside; RectF mRect = new RectF(); @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { handler.postDelayed(runnable, delayMillis); mRunning = true; mOutside = false; mRect.set(v.getLeft(), v.getTop(), v.getRight(), v.getBottom()); break; } case MotionEvent.ACTION_MOVE: if (!mOutside) { mOutside = !mRect.contains(v.getLeft() + event.getX(), v.getTop() + event.getY()); if (mOutside) { handler.removeCallbacks(runnable); mRunning = false; } } break; case MotionEvent.ACTION_UP: { if (mRunning) v.performClick(); handler.removeCallbacks(runnable); mRunning = false; break; } case MotionEvent.ACTION_CANCEL: { handler.removeCallbacks(runnable); mRunning = false; break; } } return true; // !!! } }); }


final boolean[] isLongPress = {false}; final int duration = 3000; final Handler someHandler = new Handler(); final Runnable someCall = new Runnable() { @Override public void run() { if(isLongPress[0]) { // your code goes here } } }; someButton.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { int eventAction = event.getAction(); if(eventAction == MotionEvent.ACTION_DOWN){ isLongPress[0] = true; someHandler.postDelayed(someCall, duration); } else if (eventAction == MotionEvent.ACTION_UP) { isLongPress[0] = false; someHandler.removeCallbacks(someCall); } return false; } });