14

I am doing a project in which i want to display a particular message on single touch and another message on double touch using android.How can i implement it.

My sample code is below

if(firstTap){
            thisTime = SystemClock.timeMillis();
            firstTap = false;
        }else{
            prevTime = thisTime;
            thisTime = SystemClock.uptimeMillis();

            //Check that thisTime is greater than prevTime
            //just incase system clock reset to zero
            if(thisTime > prevTime){

                //Check if times are within our max delay
                if((thisTime - prevTime) <= DOUBLE_CLICK_MAX_DELAY){

                    //We have detected a double tap!
                    Toast.makeText(AddLocation.this, "DOUBLE TAP DETECTED!!!", Toast.LENGTH_LONG).show();
                    //PUT YOUR LOGIC HERE!!!!

                }else{
                    //Otherwise Reset firstTap
                    firstTap = true;
                }
            }else{
                firstTap = true;
            }
        }
        return false;
Community
  • 1
  • 1
Sanal Varghese
  • 1,465
  • 4
  • 23
  • 46
  • 3
    Have you considered using long press as an alternative to double click? – Davek804 Apr 02 '12 at 05:21
  • see this (Implement double click for button in Android)[http://stackoverflow.com/questions/4849115/implement-double-click-for-button-in-android] – ρяσѕρєя K Apr 02 '12 at 05:22
  • 1
    please follow the android usage pattern and use long press. Don't do double click. – Win Myo Htet Apr 02 '12 at 05:23
  • Just want to help, i post an answer [HERE][1] [1]: http://stackoverflow.com/questions/20595003/how-to-detect-double-taps-on-listview-items-in-android/29564226#29564226 – tomisyourname Apr 10 '15 at 15:30
  • I post an answer [HERE][1]. Just want to help. :D [1]: http://stackoverflow.com/questions/20595003/how-to-detect-double-taps-on-listview-items-in-android/29564226#29564226 – tomisyourname Apr 10 '15 at 15:32

11 Answers11

14

Try to use GestureDetector.

public class MyView extends View {

GestureDetector gestureDetector;

public MyView(Context context, AttributeSet attrs) {
    super(context, attrs);
    // creating new gesture detector
    gestureDetector = new GestureDetector(context, new GestureListener());
}

// skipping measure calculation and drawing

// delegate the event to the gesture detector
@Override
public boolean onTouchEvent(MotionEvent e) {
    //Single Tap
    return gestureDetector.onTouchEvent(e);
}


private class GestureListener extends GestureDetector.SimpleOnGestureListener {

    @Override
    public boolean onDown(MotionEvent e) {
        return true;
    }

    // event when double tap occurs
    @Override
    public boolean onDoubleTap(MotionEvent e) {
        float x = e.getX();
        float y = e.getY();

        Log.d("Double Tap", "Tapped at: (" + x + "," + y + ")");

        return true;
    }

}
Naveen Tamrakar
  • 3,349
  • 1
  • 19
  • 28
Bhavin
  • 6,020
  • 4
  • 24
  • 26
12

Why dont you use Long Press event insted while its Recommanded UI. Read Answer Here , I strongly recommand to use this.

Or if its anyhow you want to implement you have two options , one is this using boolean and second is using Gesture Listener.

Community
  • 1
  • 1
MKJParekh
  • 34,073
  • 11
  • 87
  • 98
  • 4
    I feel this answer may be dated now. Double clicking is a common interaction on desktop layouts, and while Android isn't a desktop os, ChromeOS is, and now supports Android apps, so whether or not we should be using double-click may vary situation to situation. Long pressing with a mouse is going to be bad UX. – JediBurrell Jun 13 '18 at 22:37
  • Another reason to agree with @JediBurrell is for consistency for a given app. We're just porting our Win/iOS/OSX app to Android. Our users are used to double-tapping to take a certain action, and it would be very odd to make Android the only platform where they have to long-press instead. – Nanki Sep 24 '21 at 08:02
10

It is hold, but,for new readers, I made a small library to simplify this kind of stuff, check this article: Double click listener on android.

The library is very small, and here is the GitHub Repository Link.

And you will just use it like this:

Button btn = new Button(this);

btn.setOnClickListener( new DoubleClick(new DoubleClickListener() {
        @Override
        public void onSingleClick(View view) {

            // Single tap here.
        }

        @Override
        public void onDoubleClick(View view) {

            // Double tap here.
        }
    });
Pedro Massango
  • 4,114
  • 2
  • 28
  • 48
5

you can use on long click instead of using double click by override this method

 abstract boolean onLongClick(View v)

Called when a view has been clicked and held.

Lucifer
  • 29,392
  • 25
  • 90
  • 143
Rahul
  • 757
  • 2
  • 8
  • 13
2

You may employ RxAndroid in that case in Kotlin it shall be like this:

yourView.clicks().buffer(500, TimeUnit.MILLISECONDS, 2).filter {
    it.size >= 2
}.subscribe {
    // Handle double click
}
  1. We apply clicks() extension function on a given view which creates an RX observable sequence.
  2. We tell RX to emit an event after either 500 ms or 2 consecutive clicks take place within 500 ms.
  3. We tell RX to take only the events only with 2 consecutive click
  4. Last but not least we subscribe to the event sequence which is our DoubleClick handler
Archibald
  • 1,305
  • 1
  • 14
  • 19
2

I did a simple solution like that -

buttonTab.setOnClickListener(new View.OnClickListener() {
            int count = 0;
            Handler handler = new Handler();
            Runnable runnable = () -> count = 0;

            @Override
            public void onClick(View v) {
                if (!handler.hasCallbacks(runnable))
                    handler.postDelayed(runnable, 500);
                if(count==2){
                    /*View is double clicked.Now code here.*/
                }
            }
        });
Gk Mohammad Emon
  • 6,084
  • 3
  • 42
  • 42
2

Try the below modified code::

//Check that thisTime is greater than prevTime
//just incase system clock reset to zero
static prevTime = 0;
thisTime = Calendar.getInstance().getTimeInMillis();
if(prevTime < thisTime) {
    //Check if times are within our max delay
    if((thisTime - prevTime) <= 1000) {  //1 SEC
        //We have detected a double tap!
        Toast.makeText(AddLocation.this, "DOUBLE TAP DETECTED!!!", Toast.LENGTH_LONG).show();
        prevTime = thisTime;
        //PUT YOUR LOGIC HERE!!!!
    } else {
        //Otherwise Reset firstTap
        firstTap = true;
    }
} else {
    firstTap = true;
}
gotwo
  • 663
  • 8
  • 16
Shankar Agarwal
  • 34,573
  • 7
  • 66
  • 64
1

I have Implemented the code on which the Background color and text color changes on clicking the screen twice(Double Tap) here is the code...

        int i = 0;
        reader.setOnClickListener(new View.OnClickListener() {
            int i = 0;
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                i++;
                Handler handler = new Handler();
                Runnable r = new Runnable() {

                    @Override
                    public void run() {
                        i = 0;
                    }
                };

                if (i == 1) {
                    //Single click
                    handler.postDelayed(r, 250);
                } else if (i == 2) {

                    if(color==1) {

                        reader.setTextColor(0xFF000000);
                        reader.setBackgroundColor(0xFFFFFFFF);
                        color = 2;
                    }else if(color==2)
                    {
                        reader.setTextColor(0xFFFFFFFF);
                        reader.setBackgroundColor(0xFF000000);
                        color=1;
                    }
                    i = 0;

                }


            }
        });
1

We have extended the OnClickListener so it can be easily applied to any view:

/**
 * Allows to set double click events on views.
 *
 * @param action The action to perform on click.
 * @param interval The maximum interval between two clicks, in milliseconds.
 */
class DoubleClickListener(private val action: (view: View) -> Unit, private val interval: Long = 800) : View.OnClickListener {

    companion object {

        /** The view that was clicked previously. */
        private var myPreviouslyClickedView: WeakReference<View>? = null

        /**
         * Check if the click was a second one or not.
         * @param view The view to check for.
         *
         * @return True if the click was a second one.
         */
        private fun isSecondClick(view: View) =
            myPreviouslyClickedView?.get() == view

    }

    /** Execute the click. */
    override fun onClick(view: View?) {
        if (view != null) {

            // Make sure this click is the second one
            if (isSecondClick(view)) {
                myPreviouslyClickedView?.clear()
                action(view)

            } else {

                // Set the previous view to this one but remove it after few moments
                myPreviouslyClickedView = WeakReference(view)
                view.postDelayed({ myPreviouslyClickedView?.clear() }, interval)
            }
        }
    }

}

The property myPreviouslyClickedView ensures that there can be multiple views using the listener.

Part 2

Further, we made it a bit easier to assign the listener by extending the View:

/**
 * Set a double click listener on a view.
 *
 * @param action The action to perform on a double click.
 */
fun View.setOnDoubleClickListener(action: (view: View) -> Unit) =
    this.setOnClickListener(DoubleClickListener(action))

Or, to handle custom intervals between two clicks:

/**
 * Set a double click listener on a view.
 *
 * @param interval The maximum interval between two clicks, in milliseconds.
 * @param action The action to perform on a double click.
 */
fun View.setTimedOnDoubleClickListener(interval: Long, action: (view: View) -> Unit) =
    this.setOnClickListener(DoubleClickListener(action, interval))

Sabo
  • 1,635
  • 1
  • 19
  • 24
1

here is full example double-tap listener in kotlin


class MainActivity : AppCompatActivity() {

    private lateinit var gDetector : GestureDetectorCompat
    private lateinit var touchListener : View.OnTouchListener

    @SuppressLint("ClickableViewAccessibility")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // instantiate GestureDetectorCompat
        gDetector = GestureDetectorCompat(
                      this,
                      GestureDetector.SimpleOnGestureListener()
                    )

        // Create anonymous class extend OnTouchListener and SimpleOnGestureListener
        touchListener = object : View.OnTouchListener, GestureDetector.SimpleOnGestureListener() {
            override fun onTouch(view: View?, event: MotionEvent?): Boolean {

                gDetector.onTouchEvent(event)
                gDetector.setOnDoubleTapListener(this)

                return true
            }

            override fun onDoubleTap(e: MotionEvent?): Boolean {
                Log.i("debug", "onDoubleTap")
                return true
            }
        }

        anyView.setOnTouchListener(touchListener)

   }
}
Muhammad Rio
  • 759
  • 5
  • 6
0

Subclass View.OnClickListener

I have created a DoubleClickListener using an interface and a Thread. It can be used with any View just like classic ClickListener. This is how you can add my listener for double click events.

Example,

button.setOnClickListener(new DoubleTapListener(this));

And in any Activity, Override this method to perform task

@Override
public void onDoubleClick(View v) {
    // Do what you like
}

Implementation:

Let's see the implementation. I have created a simple DoubleTapListener but using this approach you can create complex touch listeners(Tripletouch Listener, single, double, triple listener all in one).

1) DoubleTapListener

public class DoubleTapListener  implements View.OnClickListener{

      private boolean isRunning= false;
      private int resetInTime =500;
      private int counter=0;

      private DoubleTapCallback listener;

      public DoubleTapListener(Context context)
      {
          listener = (DoubleTapCallback)context;             
      }

      @Override
      public void onClick(View v) {

         if(isRunning)
         {
            if(counter==1) //<-- makes sure that the callback is triggered on double click
            listener.onDoubleClick(v);
         }

         counter++;

         if(!isRunning)
         {
            isRunning=true;
            new Thread(new Runnable() {
                @Override
                public void run() {
                   try {
                      Thread.sleep(resetInTime);
                      isRunning = false;
                      counter=0;
                   } catch (InterruptedException e) {
                    e.printStackTrace();
                   }
                }
            }).start();
         }

      }

}

2) DoubleTapCallback

public interface DoubleTapCallback {

     public void onDoubleClick(View v);
}

3) Implement callback in your activity and override the method

public class MainActivity extends AppCompatActivity implements DoubleTapCallback{

      private Button button;       

      @Override
      protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_main);

            button   = (Button)findViewById(R.id.button);    
            button.setOnClickListener(new DoubleTapListener(this));  //<-- Set listener

      }

      @Override
      public void onDoubleClick(View v) {
            // Toast to show double click        
      }
 }

Relevant link:

You can see the full code implementation HERE

Rohit Singh
  • 16,950
  • 7
  • 90
  • 88