I'll admit straight off that I'm new to development and trying my hand at Android. I've been trying to search the 'net to find advice on how to implement some "Hold Button to Repeat Action" - I've created a custom numpad from buttons and want a backspace-like behaviour. Having got so far, I called upon a friend who hasnt coded Android before, but done lots of C# / Java and seems to know what he's doing.

The code below works just fine, but I feel it could be done more neatly. I apologise if I've missed bits out, but hopefully this explains my approach. I think the onTouchListener is ok, but the way Threads are handled doesnt feel right.

I like this implementation. There is one error in it however. The onTouch functin should return true, at least in the ACTION_DOWN case, otherwise no other touch events will be detected (the ACTION_UP in this case will never be called)
– bbedwardFeb 1 '13 at 17:18

This is a really good solution. But make sure to implement ACTION_CANCEL as in sephiron's answer too.
– Leo LandauAug 11 '14 at 18:07

Great solution, thank a lot. Also adding downView.setPressed(true); in ACTION_DOWN and downView.setPressed(false); in ACTION_CANCEL/ACTION_UP sections will make the listener to respond to selector if any.
– vir usOct 13 '15 at 0:40

1

To decouple even more you can use the normal View.setOnClickListener (or android:onClick), if you use pass (View view) -> view.performClick() in the RepeatListener constructor. As a bonus it'll fire an accessibility event (and the click sound) every time the repeat happens.
– TWiStErRobJul 22 '16 at 14:01

I think this is a great solution. I changed the performClick() to performLongClick() and moved performClick() into the ACTION_UP condition. Only problem I have is that my buttons don't animate now.
– SparkyNZOct 3 '14 at 22:31

Your basic implementation is sound. However, I would encapsulate that logic into another class so that you can use it in other places without duplicating code. See e.g. this implementation of "RepeatListener" class that does the same thing you want to do, except for a seek bar.

Oliv's RepeatListenerClass is pretty good, but it does not handle "MotionEvent.ACTION_CANCEL", so handler does not remove call back in that action. This makes problems in PagerAdapter, and so on. So I added that event case.

Instead of taking a click listener and calling onClick directly, it calls performClick or performLongClick on the view. This will trigger standard clicking behavior, like haptic feedback on long click.

It can be configured to either fire the onClick immediately (like the original), or only on ACTION_UP and only if no click events have fired (more like how standard onClick works).

Alternate no-arg constructor that sets immediateClick to false and uses the system-standard long press timeout for both intervals. To me this feels the most like what a standard "repeat long press" would be, if it existed.