Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding onTouchEvent competing with ScrollView

From a simplistic overview I have a custom View that contains some bitmaps the user can drag around and resize.

The way I do this is fairly standard as in I override onTouchEvent in my CustomView and check if the user is touching within an image, etc.

My problem comes when I want to place this CustomView in a ScrollView. This works, but the ScrollView and the CustomView seem to compete for MotionEvents, i.e. when I try to drag an image it either moves sluggishly or the view scrolls.

I'm thinking I may have to extend a ScrollView so I can override onInterceptTouchEvent and let it know if the user is within the bounds of an image not to try and scroll. But then because the ScrollView is higher up in the hierarchy how would I get access to the CustomView's current state?

Is there a better way?

like image 645
brk3 Avatar asked May 31 '11 23:05

brk3


2 Answers

Normally Android uses a long press to begin a drag in cases like these since it helps disambiguate when the user intends to drag an item vs. scroll the item's container. But if you have an unambiguous signal when the user begins dragging an item, try getParent().requestDisallowInterceptTouchEvent(true) from the custom view when you know the user is beginning a drag. (Docs for this method here.) This will prevent the ScrollView from intercepting touch events until the end of the current gesture.

like image 167
adamp Avatar answered Oct 11 '22 10:10

adamp


None of the solutions found worked "out of the box" for me, probably because my custom view extends View, not ViewGroup, and thus I can't implement onInterceptTouchEvent.

Also calling getParent().requestDisallowInterceptTouchEvent(true) was throwing NPE, or doing nothing at all.

Finally this is how I solved the problem:
Inside your custom onTouchEvent call requestDisallow... when your view will take care of the event. For example:

@Override
public boolean onTouchEvent(MotionEvent event) {
    Point pt = new Point( (int)event.getX(), (int)event.getY() );
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        if (/*this is an interesting event my View will handle*/) {
            // here is the fix! now without NPE
            if (getParent() != null) {
                getParent().requestDisallowInterceptTouchEvent(true);
            }

            clicked_on_image = true;
        }
    } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
        if (clicked_on_image) {
            //do stuff, drag the image or whatever
        }
    } else if (event.getAction() == MotionEvent.ACTION_UP) {
        clicked_on_image = false;
    }
    return true;
}

Now my custom view works fine, handling some events and letting scrollView catch the ones we don't care about. Found the solution here: http://android-devblog.blogspot.com.es/2011/01/scrolling-inside-scrollview.html

Hope it helps.

like image 20
Salvatorelab Avatar answered Oct 11 '22 10:10

Salvatorelab