Search code examples
androidevent-handlingtouch-eventandroid-event

How to distinguish between move and click in onTouchEvent()?


In my application, I need to handle both move and click events.

A click is a sequence of one ACTION_DOWN action, several ACTION_MOVE actions and one ACTION_UP action. In theory, if you get an ACTION_DOWN event and then an ACTION_UP event - it means that the user has just clicked your View.

But in practice, this sequence doesn't work on some devices. On my Samsung Galaxy Gio I get such sequences when just clicking my View: ACTION_DOWN, several times ACTION_MOVE, then ACTION_UP. I.e. I get some unexpectable OnTouchEvent firings with ACTION_MOVE action code. I never (or almost never) get sequence ACTION_DOWN -> ACTION_UP.

I also cannot use OnClickListener because it does not gives the position of the click. So how can I detect click event and differ it from move?


Solution

  • Here's another solution that is very simple and doesn't require you to worry about the finger being moved. If you are basing a click as simply the distance moved then how can you differentiate a click and a long click.

    You could put more smarts into this and include the distance moved, but i'm yet to come across an instance when the distance a user can move in 200 milliseconds should constitute a move as opposed to a click.

    setOnTouchListener(new OnTouchListener() {
        private static final int MAX_CLICK_DURATION = 200;
        private long startClickTime;
    
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    startClickTime = Calendar.getInstance().getTimeInMillis();
                    break;
                }
                case MotionEvent.ACTION_UP: {
                    long clickDuration = Calendar.getInstance().getTimeInMillis() - startClickTime;
                    if(clickDuration < MAX_CLICK_DURATION) {
                        //click event has occurred
                    }
                }
            }
            return true;
        }
    });