【问题标题】:Single click and double click of a button in android在android中单击和双击一个按钮
【发布时间】:2013-03-12 04:42:08
【问题描述】:

在我的应用程序中,我有一个按钮。单击按钮和双击按钮后将执行单独的操作。我怎样才能做到这一点?谢谢

【问题讨论】:

  • 只需在点击事件中设置一个全局变量count并递增。当count=2时执行双击操作并重置为count=0。

标签: android button onclicklistener


【解决方案1】:

您可能需要创建一个延迟变量来区分单击和双击。

看这段代码,

private static final long DOUBLE_PRESS_INTERVAL = 250; // in millis
private long lastPressTime;

private boolean mHasDoubleClicked = false;

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {    

        // Get current time in nano seconds.
        long pressTime = System.currentTimeMillis();


        // If double click...
        if (pressTime - lastPressTime <= DOUBLE_PRESS_INTERVAL) {
            Toast.makeText(getApplicationContext(), "Double Click Event", Toast.LENGTH_SHORT).show();
            mHasDoubleClicked = true;
        }
        else {     // If not double click....
            mHasDoubleClicked = false;
            Handler myHandler = new Handler() {
                 public void handleMessage(Message m) {
                      if (!mHasDoubleClicked) {
                            Toast.makeText(getApplicationContext(), "Single Click Event", Toast.LENGTH_SHORT).show();
                      }
                 }
            };
            Message m = new Message();
            myHandler.sendMessageDelayed(m,DOUBLE_PRESS_INTERVAL);
        }
        // record the last time the menu button was pressed.
        lastPressTime = pressTime;      
        return true;
    }

【讨论】:

  • 您好,感谢您的回复。实际上我需要知道如何在按钮中应用它,因为我是 android 的新手
  • @Rynold,我使用了你的代码,当我双击时,单击内的代码也会执行。你能帮帮我吗?
  • 为什么使用处理程序类@Raynold
  • 我认为你应该使用 ViewConfiguration.getDoubleTapTimeout() 作为 DOUBLE_PRESS_INTERVAL,以与其他 Android 双击保持一致。
【解决方案2】:

这很简单,只需覆盖即可。

OnClickListener的onClick方法

public abstract class DoubleClickListener implements View.OnClickListener {
private static final long DEFAULT_QUALIFICATION_SPAN = 200;
private boolean isSingleEvent;
private long doubleClickQualificationSpanInMillis;
private long timestampLastClick;
private Handler handler;
private Runnable runnable;

public DoubleClickListener() {
    doubleClickQualificationSpanInMillis = DEFAULT_QUALIFICATION_SPAN;
    timestampLastClick = 0;
    handler = new Handler();
    runnable = new Runnable() {
        @Override
        public void run() {
            if (isSingleEvent) {
                onSingleClick();
            }
        }
    };
}

@Override
public void onClick(View v) {
    if((SystemClock.elapsedRealtime() - timestampLastClick) < doubleClickQualificationSpanInMillis) {
        isSingleEvent = false;
        handler.removeCallbacks(runnable);
        onDoubleClick();
        return;
    }

    isSingleEvent = true;
    handler.postDelayed(runnable, DEFAULT_QUALIFICATION_SPAN);
    timestampLastClick = SystemClock.elapsedRealtime();
}

public abstract void onDoubleClick();
public abstract void onSingleClick();
}

用法

 button.setOnClickListener(new DoubleClickListener() {
        @Override
        public void onDoubleClick() {
            Log.i("onClick", "double");
        }

        @Override
        public void onSingleClick() {
            Log.i("onClick", "single");
        }
    });

【讨论】:

  • 应该是公认的答案,因为它完全符合预期
  • 我也能找到最佳答案。我发布了一个 Kotlin 翻译,以防任何人发现它有用。史蒂夫·S.
【解决方案3】:

您可能需要考虑不使用 DoubleTap。这不是正常的 Android 行为。

当我第一次开始在 Android 上编程时,我不断遇到在 android 上真正“难”做的事情。久而久之,我发现其中很多都是困难的,因为它们是一个非常糟糕的主意。

如果您要移植 iOS 应用或模拟 iOS 应用的行为,您可能需要考虑将 UI 转换为 Android 风格的行为并使用 longPress 或其他“androidy”手势。

这是一个类似的问题和答案:

Android: How to detect double-tap?

【讨论】:

    【解决方案4】:

    您必须实现 GestureDetector 并将您的代码放入single/double click

    TestActivity.java

    iv.setOnClickListener(new OnClickListener() {           
                    @Override
                    public void onClick(View v) {
                        //putyour first activity call.
                    }
        }
    
    iv.setOnTouchListener(new OnTouchListener() {
                 GestureDetector gestureDetector = new GestureDetector(context, new MyGestureDetector(context));
             @Override
             public boolean onTouch(View v, MotionEvent event) {
                    return gestureDetector.onTouchEvent(event);
             }
    });
    

    现在你必须创建GestureDetector.java 类。

    public class MyGestureDetector extends SimpleOnGestureListener {
        public Context context;
        public String phno;
    
        public MyGestureDetector(Context con) {
            this.context=con;       
        }
    
        @Override
        public boolean onDown(MotionEvent e) {
            return super.onDown(e);
        }
    
        @Override
        public boolean onDoubleTap(MotionEvent e) {
            System.out.println("in Double tap");
    
            return true;
        }
    
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            System.out.println("in single tap up");
                //put your second activity.
            return super.onSingleTapUp(e);
        }   
    }
    

    【讨论】:

    • 您好,感谢您的回复。通过此代码,当我尝试执行双点触控操作时,它也会执行单点触控操作。双触时如何停止单触操作?
    • @andDev 您必须在单击/双击时要求相同的函数调用,所以有什么问题?
    • 实际上我需要为单点和双点触控处理两个活动
    • public boolean onDoubleTap(MotionEvent e) { // System.out.println("in Double tap");标志 = 2; Intent intent=new Intent(getApplicationContext(),Click2.class);开始活动(意图);返回真; } @Override public boolean onSingleTapUp(MotionEvent e) { // System.out.println("单点向上");标志=1; Intent intent=new Intent(getApplicationContext(),Click1.class);开始活动(意图);返回 super.onSingleTapUp(e); }
    • 同样的问题。两个活动同时开始
    【解决方案5】:

    感谢 @NikolaDespotoski

    您可以从以下 URL 中查看 DOUBLE-TAP 示例。 在 listView 中使用。希望对你有用。

    https://nodeload.github.com/NikolaDespotoski/DoubleTapListView/zip/master

    【讨论】:

      【解决方案6】:

      虽然为时已晚,但任何人都可以弄清楚他们是否看到了这一点。

      int number_of_clicks = 0;
      boolean thread_started = false;
      final int DELAY_BETWEEN_CLICKS_IN_MILLISECONDS = 250;
      
      button.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              ++number_of_clicks;
              if(!thread_started){
                  new Thread(new Runnable() {
                      @Override
                      public void run() {
                          thread_started = true;
                          try {
                              Thread.sleep(DELAY_BETWEEN_CLICKS_IN_MILLISECONDS);
                              if(number_of_clicks == 1){
                                  client.send(AppHelper.FORMAT_LEFT_CLICK);
                              } else if(number_of_clicks == 2){
                                  client.send(AppHelper.FORMAT_DOUBLE_CLICK);
                              }
                              number_of_clicks = 0;
                              thread_started = false;
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                      }
                  }).start();
              }
          }
      });
      

      解释:


      在按钮点击之前,number_of_click 被初始化为 0。 thread_started 是一个标志,用于检测线程之前是否启动过。 现在,在单击按钮时,通过增量运算符增加按钮单击的次数。 检查线程是否之前启动过,如果没有,则启动线程。 在线程上,使用 number_of_clicks 应用您的逻辑。并且线程将等待下一毫秒,然后将通过您的逻辑。 因此,现在您可以根据需要应用任意数量的点击。

      【讨论】:

        【解决方案7】:

        通过继承View.OnClickListener并检查点击时间来区分单击或双击来解决这个问题,这也解决了快速点击的问题。此解决方案将带来较小的代码更改,只需替换 View.OnClickLister。您还可以覆盖 getGap() 以重新定义两次单击之间的时间。

        import android.os.SystemClock;
        import android.view.View;
        
        /*****
         * Implement to fix the double click problem.
         * Avoid the fast double click for button and images.
         */
        public abstract class OnSingleClickListener implements View.OnClickListener {
            private long prevClickTime =0;
        
            @Override
            public void onClick(View v) {
                _onClick(v);
            }
        
            private synchronized void _onClick(View v){
                long current = SystemClock.elapsedRealtime();
                if(current-prevClickTime> getGap()){
                    onSingleClick(v);
                    prevClickTime = SystemClock.elapsedRealtime();
                }else {
                    onDoubleClick(v);
                    prevClickTime = 0;
                }
            }
        
            public abstract void onSingleClick(View v);
            public abstract void onDoubleClick(View v);
        
            /********
             *
             * @return The time in ms between two clicks.
             */
            public long getGap(){
                return 500L; //500ms
            }
        }
        

        【讨论】:

          【解决方案8】:

          这是@saksham 在 Kotlin 中的回答。

          abstract class DoubleClickListener : View.OnClickListener {
              private val DEFAULT_QUALIFICATION_SPAN = 200L
              private var isSingleEvent = false
              private val doubleClickQualificationSpanInMillis =
                  DEFAULT_QUALIFICATION_SPAN
              private var timestampLastClick = 0L
              private val handler = Handler(Looper.getMainLooper())
              private val runnable: () -> Unit = {
                  if (isSingleEvent) {
                      onSingleClick()
                  }
              }
              override fun onClick(v: View) {
                  if (SystemClock.elapsedRealtime() - timestampLastClick < doubleClickQualificationSpanInMillis) {
                      isSingleEvent = false
                      handler.removeCallbacks(runnable)
                      onDoubleClick()
                      return
                  }
                  isSingleEvent = true
                  handler.postDelayed(runnable, DEFAULT_QUALIFICATION_SPAN)
                  timestampLastClick = SystemClock.elapsedRealtime()
              }
          
              abstract fun onDoubleClick()
              abstract fun onSingleClick()
          }
          

          【讨论】:

            【解决方案9】:

            up的解决方案不能用于多次点击,我测试过但失败了。

            所以我建议将 RxBinding 与 ProgressDialog 一起使用。

            当点击按钮时,progressDialog显示设置不能取消,修复它。

            【讨论】:

              【解决方案10】:

              我也遇到过同样的问题

              setOnClickListener(new OnClickListener() {           
                          @Override
                          public void onClick(View v) {
                              if(isFmOn()){
                                 //stopFM
                              }else{
                                //do other things
                              }
                          }
              }
              

              当我单击按钮时,FM停止;但是当我双击时,FM并没有停止。问题是单击按钮和双击按钮时,isFmOn()的值是不同的。 我用这个解决了这个问题:

              setOnClickListener(new OnClickListener() {           
                          @Override
                          public void onClick(View v) {
                              Thread.sleep(500);//500ms was enough to finish stopFM before the second click
                              if(isFmOn()){
                                 //stopFM
                              }else{
                                //do other things
                              }
                          }
              }
              

              【讨论】:

              • Ugg,在 UI 线程中休眠可不是什么好事!我也没有回答 OP 的问题。
              • 单击按钮和双击按钮后会执行单独的操作,可能是onClick()函数的问题,有时释放音频资源时,必须等到释放操作完成。也许解决问题的更好方法是简单地设置一个全局变量计数并增加点击次数。
              猜你喜欢
              • 2015-04-24
              • 2018-02-04
              • 2011-06-18
              • 2014-01-12
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-12-04
              相关资源
              最近更新 更多