Reputation: 844
I have a view that covers entire screen (let's say ParentView
), and child inner view ChildView
that covers only portion of it.
I want to make ChildView
to respond to onSingleTapUp()
, while the ParentView
respond to onFling()
. I am trying to do so by attaching one SimpleOnGestureListener
on ChildView
and one SimpleOnGestureListener
on ParentView
.
To accept onSingleTapUp()
from ChildView
, its listener's onDown()
has to return true.
But once I do that, the listener tied to ParentView
does not hear any motion events anymore since it is taken by the ChildView
's listener. Even though ChildView
's onFling()
returns false, the events do not flow to the ParentView
's listener.
How can I make the parent view's listener catch the fling gesture while child view's listener catch tap gesture?
I don't think any source code is needed to explain the situation, but here is a snippet that sets up my ChildView
listener.
ChildView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return singleTapGestureDetector.onTouchEvent(motionEvent);
}
});
One workaround could be to have both ParentView
and ChildView
's listeners to handle onFling()
while only ChildView
's listener handle onSingleTapUp()
, but in that case, fling won't be able to happen across the ChildView
(like start outside the child and then end within the child), I believe.
Upvotes: 5
Views: 2577
Reputation: 844
I don't like my solution, but I found a way to do this. Hopefully somebody else will post better answer in the future, or at least my workaround is useful to somebody otherwise.
As I described in the question, the problem lies on how gesture listener works. For child view to catch onSingleTapUp()
event, you return true on onDown()
. But once you do that, the subsequent series of events won't go to the parent view even after your child view's onTouch()
declares it is no longer interested in the event. If you forcefully call the parent's onTouch()
within the child's onTouch()
when its gesture detector returns false, yes the parent's onFling() will be invoked but the first MouseEvent
argument will be NULL since it was consumed by the child view's onTouch()
.
I must be missing something since this seems very basic gesture detection scenario. Anyway, I couldn't find a way to do this in reasonable way.
So, my workaround is to make TouchListenerService as a singleton.
Both child view and parent view have this line:
view.setOnTouchListener(TouchListenerService.Instance());
and TouchListenerService starts like this:
public class TouchListenerService
extends GestureDetector.SimpleOnGestureListener
implements View.OnTouchListener {
// some code to implement singleton
public SingleTapUpHandler SingleTapUpHandler;
public FlingHandler FlingHandler;
private View _touchingView;
GestureDetector gestureDetector;
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (gestureDetector == null)
gestureDetector = new GestureDetector(_touchListenerService);
_touchingView = view;
boolean result = gestureDetector.onTouchEvent(motionEvent);
_touchingView = null;
return result;
}
// and some more code
Since it is the same event handler, parent view catches onFling()
event successfully while child view can set SingleTapUpHandler
to process click event.
Upvotes: 2