package org.ccci.gto.android.common.widget;

import android.view.MotionEvent;
import android.view.View;

public class RepeatingClickTouchListener implements View.OnTouchListener {
    private long initialDelay = 500;
    private long repeatingDelay = 100;

    private Runnable task;

    @Override
    public boolean onTouch(final View v, final MotionEvent event) {
        int action = event.getAction();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //Just to be sure that we removed all callbacks,
                // which should have occurred in the ACTION_UP
                v.removeCallbacks(this.task);

                //Perform the default click action.
                v.performClick();

                // create a runnable task for the view
                this.createTask(v);

                //Schedule the start of repetitions after the initial delay.
                v.postDelayed(this.task, this.initialDelay);

                return true;
            case MotionEvent.ACTION_UP:
                //Cancel any repetition in progress.
                v.removeCallbacks(this.task);

                // reset task
                this.task = null;

                return true;
        }

        // we didn't consume the event, so let other handlers possible take it
        return false;
    }

    private void createTask(final View v) {
        this.task = new Runnable() {
            @Override
            public void run() {
                // Perform the present repetition of the click action provided by the user
                // in setOnClickListener().
                v.performClick();

                // Schedule the next repetitions of the click action, using a faster repeat
                // interval than the initial repeat delay interval.
                v.postDelayed(task, repeatingDelay);
            }
        };
    }
}

@@ -38,16 +38,42 @@
 idget;%0A%0A
+import android.util.Pair;%0A
 import a
@@ -287,16 +287,27 @@
  private
+ Pair%3CView,
  Runnabl
@@ -311,14 +311,50 @@
 able
+%3E
  task;
+%0A    private boolean fired = false;
 %0A%0A  
@@ -437,48 +437,8 @@
 ) %7B%0A
-        int action = event.getAction();%0A
     
@@ -534,117 +534,41 @@
   //
-Just to be sure that we removed all callbacks,%0A                // which should have occurred 
+ reset any currently runn
 in
+g
  t
-he ACTION_UP
+ask
 %0A   
@@ -584,120 +584,21 @@
     
-v.removeCallbacks(this.task);%0A%0A                //Perform the default click action.%0A                v.performClic
+this.resetTas
 k();
@@ -665,24 +665,36 @@
             
+ this.task =
  this.create
@@ -701,16 +701,52 @@
 Task(v);
+%0A                this.fired = false;
 %0A%0A      
@@ -757,16 +757,17 @@
       //
+ 
 Schedule
@@ -856,16 +856,23 @@
 his.task
+.second
 , this.i
@@ -901,35 +901,36 @@
          return 
-tru
+fals
 e;%0A            c
@@ -978,86 +978,176 @@
   //
-Cancel any repetition in progress.%0A                v.removeCallbacks(this.t
+ should we consume this event?%0A                final boolean consumed = this.fired;%0A%0A                // reset any currently running task%0A                this.resetT
 ask
+(
 );%0A%0A
@@ -1169,53 +1169,244 @@
  // 
-reset task%0A                this.task = null;%0A
+did we consume the event?%0A                return consumed;%0A            case MotionEvent.ACTION_CANCEL:%0A                // reset any currently running task%0A                this.resetTask();%0A%0A                // never consume cancel events
 %0A   
@@ -1429,11 +1429,12 @@
 urn 
-tru
+fals
 e;%0A 
@@ -1464,22 +1464,21 @@
  didn't 
-consum
+handl
 e the ev
@@ -1489,39 +1489,20 @@
  so 
-let other handlers possible tak
+don't consum
 e it
@@ -1543,20 +1543,35 @@
 private 
-void
+Pair%3CView,Runnable%3E
  createT
@@ -1598,27 +1598,48 @@
         
-this.task =
+return Pair.create(v, (Runnable)
  new Run
@@ -1857,25 +1857,117 @@
     
-v.performClick();
+if(v.isPressed()) %7B%0A                    v.performClick();%0A                    fired = true;%0A                %7D
 %0A%0A  
@@ -2155,19 +2155,19 @@
 elayed(t
-ask
+his
 , repeat
@@ -2200,17 +2200,270 @@
        %7D
-;
+);%0A    %7D%0A%0A    public void resetTask() %7B%0A        if(this.task != null) %7B%0A            //Cancel any repetition in progress.%0A            this.task.first.removeCallbacks(this.task.second);%0A%0A            // clear the task%0A            this.task = null;%0A        %7D
 %0A    %7D%0A%7D

make touch handling more robust to prevent several weird touch interactions