I have implemented custom view with some children. The view can be scrolled using standard drag gesture. Also every child can be clicked. The problem is, that when I start dragging the view, one of children gets ‘down’ event and it changes its state to ‘pressed’ for a second. I would prefer standard listview behavior – the child goes into pressed state when the user keeps pressing this child with his/her finger for like 50ms. It would reduce blinking caused by misread press event.
I know, that I need at least 2 events to detect if the user is tapping or dragging the view. For now I’m using TimerTask to shedule ‘down’ event. When I get ‘move’ event before my ‘down’ event is executed, I know that the user is dragging and I can cancel the sheduled event.
I know it’s quite hacky. I also tried gesturedetector to detect drag and tap events, but it needs some additional work to properly implement changing view state from pressed to default when the user moves finger and starts to drag the view.
My question is – how this is implemented in android listview? I tried to copy their solution from listview implementation, but it’s so huge I can’t handle it. Simply I don’t see the code responsible for handling such situation.
I managed to understand a gesture detection logic in ListView and, in general, in android views. I wrote my own gesture detector, which is somewhat better than the original one. It reports more gestures (multiple taps, dragging) and has some configurables (timeouts, move epsilon). You can find it open-sourced here: Better Gesture Detector on code.google
The library uses Handler class and postDelayed()/removeCallbacks() method combination to detect, handle and cancel motion events and gestures. It’s quite simple and one should be able to get the idea by just reading the code.
This repository also contains a simple demo. Please note that this code is provided ‘as is’, contains some useless comments, logs and should be cleaned up a bit.