Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: ViewGroup, how to intercept MotionEvent and then dispatch to target or eat it on demand?

Given that there is a ViewGroup with several children. As for this ViewGroup, I'd like to have it managing all MotionEvent for its all children, which says VG will
1. be able to intercept all events before they get dispatched to target (children)
2. VG will first consume the event, and determine if will further dispatch event to target child
3. DOWN, MOVE, UP, I'd like to see them as relatively independent, which means VG could eat DOWN, but give MOVE and UP to children.

I've read SDK guide "Handling UI Event", I knew event listeners, handlers, ViewGroup.onInterceptTouchEvent(MotionEvent), and View.onTouchEvent(MotionEvent).

Here's my sample,

@Override
public boolean onInterceptTouchEvent (MotionEvent event) {
    if (MotionEvent.ACTION_DOWN == event.getAction()) {
        return true;
    }

    return super.onInterceptTouchEvent(event);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (MotionEvent.ACTION_DOWN == event.getAction()) {            
        return true;
    }
    else {
        if (!consumeEvent(event)) {
            // TODO: dispatch to target since I didn't want to eat event
            //return this.dispatchTouchEvent(event);     // infinite loop!!!
        }
    }


    return super.onTouchEvent(event);
}

To be able to eat some events, I have to return true in above both methods when DOWN event occurred, because SDK said so. Then I could see MOVE and up in onTouchEvent. However, in my case, I've no idea about how to dispatch event to children.

Above dispatchTouchEvent led to infinite loop, which was understandable, since VG itself might be the target. I can't tell which would be target at that moment, MotionEvent didn't give a hint, so dispatchTouchEvent was totally useless.
Anyone help me out? Thanks.

like image 709
fifth Avatar asked Oct 11 '22 02:10

fifth


1 Answers

There is no easy way to find the source View from onInterceptTouchEvent, nor there is a way to "dispatch" these events. You can dispatch KeyEvents, but not MotionEvents.

A common way to deal with MotionEvents (e.g., for drag and drop) is to handle the MotionEvent.ACTION_DOWN events by the different Views (through the onTouch callback after implementing OnTouchListener), and the MotionEvent.ACTION_MOVE events through the parent Viewgroup's onInterceptTouchEvent method.


But some LOCs say a lot more than a bunch of words. There's a very nice example of what I'm saying here: http://doandroids.com/blogs/tag/codeexample/


If you handle the ACTION_DOWN event in the View itself, then you can store which View started it elsewhere and use that variable for further actions. The Event is bound to the same View until is finished by an ACTION_UP or an ACTION_CANCEL actions.

If you need to keep track the View and execute an action on the ViewGroup during the ACTION_DOWN, then I suggest you to add a public method in your ViewGroup (e.g. public boolean handleActionDown (View v, MotionEvent e) that will be called from the onTouch callback

like image 141
Aleadam Avatar answered Oct 20 '22 12:10

Aleadam