LongClick事件发生得太快。 如何增加触发它所需的点击时间?

在我正在处理的应用程序中,我有要求用户必须在发生特定操作之前在某个时间段内点击并按住组件。

我目前使用OnLongClickListener监听longclick,但是我发现点击触发OnLongClick事件的时间太短。

例如,假设LongClick事件在400ms点击之后触发,但是我希望用户在事件触发之前必须单击并按住1200ms。

有什么办法可以configurationLongClick事件需要更长的点击?
或者,也许还有另一个构造,可以让我听更长的点击?

Solutions Collecting From Web of "LongClick事件发生得太快。 如何增加触发它所需的点击时间?"

在onLongClick事件中不可能改变定时器,它由android本身pipe理。

什么是可能的是使用.setOnTouchListener()。

然后注册MotionEvent是一个ACTION_DOWN。
记下variables中的当前时间。
然后当一个具有ACTION_UP的MotionEvent被注册,并且current_time – actionDown时间大于1200毫秒时,那么做一些事情。

非常多:

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; } }) 

我在Rohan的帮助下制定了一个解决scheme:)
我调整了他的答案以适应我的要求。

当用户按下button时,一个线程被启动。 线程睡觉我想要的延迟,然后当它醒来时,它执行任何代码,我需要它做的事情。 当用户放开时,线程被终止。 这完成了我想要的,因为如果用户在线程唤醒之前放开,线程将被中断,并且不会发生操作。

我喜欢这种方法,因为它可以让我在延迟结束后立即执行业务逻辑,这是很好的,因为我可以给用户一些反馈,让他们知道他们已经推得足够长(例如手机可以振动)。
这种方法的不足之处在于:用户在所需的操作正在运行时放开button,并在完成所有操作之前杀死线程。 这对我来说不是个大问题,因为我的业务逻辑很less; 它只是激发其他一些课程的事件来处理。 如果操作没有完全完成,则用户必须再次尝试才是可以接受的。

代码比我想要的要长一点,但是如果这是你的应用程序中的一个常见function,那么它很容易重用。 这是一个代码示例:

 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. } } } 

这是我发现实现这种行为的最简单的方法。 与目前接受的答案相比,它有两个优点。

  1. 通过检查view.isPressed我们确保onClickonLongClick在触摸事件离开视图时不被触发。 这模仿了系统默认的onClickonLongClick行为。
  2. 该事件已经存储了时间信息,所以不需要将开始时间存储在ACTION_DOWN或者自己计算ACTION_UP上的当前时间。 这意味着我们可以同时将它用于多个视图,因为我们没有在onTouch之外的单个variables中跟踪事件的开始时间。

注: ViewConfiguration.getLongPressTimeout()是默认值,您可以更改该检查以使用您需要的任何值。

注意:如果视图不能正常点击,您需要调用view.setClickable(true)来使view.isPressed()检查起作用。

 @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; } 

如果像@ ampersandre一样,在延迟期结束后立即触发long click事件,而不是等待ACTION_UP那么下面的ACTION_UP对我来说就很好。

 @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; } 
 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; } }); 

我发现了一个简单的解决scheme,研究长按事件的工作原理。 每次单击一个视图时,都会将一个types为CheckForLongPressRunnable添加到延迟队列中。 如果延迟结束,则调用OnLongClickListener 。 如果在延迟结束之前有不同的事件,则CheckForLongPress Runnable将从队列中移除。

我只是重写postDelayed(Runnable action, long delayMillis)的公共方法postDelayed(Runnable action, long delayMillis)来改变OS延迟

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

我将LONG_PRESS_MILLIS设置为100,它正在工作!

希望能帮助到你!!! ;)