安卓 - 检测长按结束

29

我正在开发一个应用程序,用户需要长时间按住按钮。

如何检测用户是:完成按下操作还是移动了触摸位置?

谢谢。


你需要进一步解释用户移动位置的重要性。至于检测长按事件的结束,只需使用setOnLongClickListener()方法即可。当用户释放按钮时,onLongClick()方法将自动被调用。 - Squonk
5
错误的,onLongClick方法是在检测到长按时立即触发的——也就是说,当“长按”超时发生时,而不是用户释放按钮时。 - John O'Connor
4个回答

68

我认为你最好使用onLongClickListener()和onTouchListener()的组合来处理该按钮。由于onTouchListener()会触发每一个触摸事件,所以你需要在触摸监听器中捕获特定的事件。

试着使用以下代码:

class Blah extends Activity {
     private Button mSpeak;
     private boolean isSpeakButtonLongPressed = false;

     @Override
     public void onCreate(Bundle icicle) {
          super.onCreate(icicle);
          setContentView(R.layout.blahlayout);
          Button mSpeak = (Button)findViewById(R.id.speakbutton);
          mSpeak.setOnLongClickListener(speakHoldListener);
          mSpeak.setOnTouchListener(speakTouchListener);
     }

     private View.OnLongClickListener speakHoldListener = new View.OnLongClickListener() {

          @Override
          public boolean onLongClick(View pView) {
               // Do something when your hold starts here.
               isSpeakButtonLongPressed = true;
               return true;
          }
     }

     private View.OnTouchListener speakTouchListener = new View.OnTouchListener() {

          @Override
          public boolean onTouch(View pView, MotionEvent pEvent) {
               pView.onTouchEvent(pEvent);
               // We're only interested in when the button is released.
               if (pEvent.getAction() == MotionEvent.ACTION_UP) {
                    // We're only interested in anything if our speak button is currently pressed.
                    if (isSpeakButtonLongPressed) {
                         // Do something when the button is released.
                         isSpeakButtonLongPressed = false;
                    }
               }
               return false;
          }
     }
}

谢谢John,非常好的解决方案。 - alfdev
4
当我长按按钮时,动作会运行两次,我通过在onTouchListener中返回true而不是false来修复它。 - DAVIDBALAS1
这正是我想要的完美之物! - X09
这怎么是个好的解决方案呢?用户必须停止触摸屏幕才能检测到 pEvent.getAction() == MotionEvent.ACTION_UP,而用户期望的是轻触并按住屏幕后自动开始处理,而不是轻触并按住然后松开。 - Bugs Happen
1
@BugsHappen - 问询者明确要求这种行为:如何检测用户完成按压的时刻。如果您想要在检测到长按(即使按钮仍被按下)后触发某种行为,您可以使用longClickListener而不是使用此技术。 - John O'Connor
哇!感谢您清晰的回答和漂亮的代码片段! - Murad Alm.

8
这些答案相当复杂。如果您从OnLongClickListener返回false,则仍会在长按结束时调用来自OnClickListeneronClick。这是检测长按结束的最简单方法。
特别需要知道的是,如果您使用onTouch并同时从onLongClick返回false(AS的默认设置且通常是您想要的),则可能会在不知情的情况下调用onClick代码以结束长按。
以下是一个基于拍摄照片或视频的示例:
private boolean takingVideo = false;

captureButton.setOnClickListener(v -> {
    // onClick gets called after normal click or long click
    if(takingVideo) {
        saveVideo();
    } else {
        takePhoto();
    }
});

captureButton.setOnLongClickListener(v -> {
    takeVideo();

    return false;
});

private void takePhoto() {
    // Save the photo
}

private void takeVideo() {
    takingVideo = true;
    // Start capturing video
}

private void saveVideo() {
    takingVideo = false;
    // Save the video
}

如您所见,当您允许Android将结束触摸事件传播给一个OnClickListener时,逻辑就变得非常直观。


“onClick在普通点击或长按后被调用。” 我无法重现这个问题。我从未在长按时听到我的clickListener。 - tir38
@tir38 你确定在 OnLongClickListener 中返回了 false 吗? - Ben Kane
我也想指出您使用了引号,但实际上我说的是onClick侦听器将在长按结束时被调用。我应该更清楚地表达,或许我应该编辑答案。我的意思是,在长时间单击后抬起手指时将调用onClick。拍照/视频示例演示了这一点。 - Ben Kane

1

-2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接