Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correctly detecting a swipe on a GridView placed inside a ViewPager in Android

Tags:

android

I have a ViewPager which uses GridViews for pages. I would like the ViewPager to switch pages when I swipe across the screen.

The problem is that swipes are not detected when they are made across the GridView. Outside of the GridView, the swipes work correctly; it seems that the GridView is trapping all touch events without passing it to ViewPager first.

While fiddling with the source code, I did this to a custom class extended from GridView:

@Override
public boolean onTouchEvent(MotionEvent event) {
    return pager.onInterceptTouchEvent(event);
}

-- where pager refers to the ViewPager class. With this, ViewPager will correctly detect swipes and move pages accordingly, but it doesn't allow GridView to accept any events, so I can't click on the items.

What I would like to be able to do is correctly detect swipes in ViewPager and item clicks on GridView.

like image 338
colig Avatar asked Mar 23 '12 12:03

colig


3 Answers

I had trouble with colig's implementation, but I was able to get it to work by subclassing ViewPager and overriding the onInterceptTouchEvent() method. I only checked for swipes in the X direction to allow for vertical scrolling if necessary.

private static final int minSwipeDistance = 30;
private float mTouchX;

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    boolean response = super.onInterceptTouchEvent(event);
    float x = event.getX();
    switch (event.getActionMasked()) {
    case MotionEvent.ACTION_DOWN:
        mTouchX = x;
        break;
    case MotionEvent.ACTION_MOVE:
        float dX = Math.abs(x - mTouchX);
        if (dX > minSwipeDistance)
            return true;
        break;
    }
    return response;
}
like image 170
Kevin Avatar answered Sep 21 '22 12:09

Kevin


Alix is on the right track. I managed to come up with this simple-looking fix. I'm not entirely sure of how it works, but it does! And for future reference, it works for other kinds of views too -- TableLayout, for example -- not just GridView.

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    x = event.getX();
    y = event.getY();
    switch (event.getActionMasked()) {
    case MotionEvent.ACTION_DOWN: {
        downX = x;
        downY = y;
        return super.onInterceptTouchEvent(event);
    }
    case MotionEvent.ACTION_MOVE: {
        deltaX = Math.abs(downX - x);
        deltaY = Math.abs(downY - y);
        return super.onTouchEvent(event);
    }
    case MotionEvent.ACTION_UP: {
        if (deltaX > 4 && deltaY > 4) {
            super.onTouchEvent(event);
        }
    }
    }
    return super.onInterceptTouchEvent(event);
}
like image 44
colig Avatar answered Sep 20 '22 12:09

colig


You can override onInterceptTouchEvent for dispatch evenement where you want

like image 27
Alix Bloom Avatar answered Sep 21 '22 12:09

Alix Bloom