Reputation: 13402
I'm using a ViewPager
in my app that houses a horizontal layout of images to implement a Paginated gallery.
When I test the view alone, i.e. as the main view of an activity, it works fine. However, when I include this as part of another layout, the scrolling (or flicking) becomes weird. If seems to reset to its original position around halfway through a swipe (really quick flicks are the only thing I've gotten to work so far).
Any ideas what the problem could be ?
Just in case it is of any relevance, the view is inflated from XML and added in a PagerAdapter
inherited class.
Upvotes: 6
Views: 2773
Reputation: 8176
Yeah, ViewPager
and other scrolling items don't play well together by default. When I have to do such things, I typically subclass ViewPager
to make something that's aware of children that can scroll. Then in my onInterceptTouchEvent()
I check whether the hit rect is within that child and don't intercept the touch event so the child has a whack at it. Something like this:
/**
* Override to not intercept touch events within our scroller if it exists.
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if(scrollerId != 0) {
View scroller = findViewById(scrollerId);
if(scroller != null) {
Rect rect = new Rect();
scroller.getHitRect(rect);
if(rect.contains((int)ev.getX(), (int)ev.getY())) {
return false;
}
}
}
return super.onInterceptTouchEvent(ev);
}
Then all you need is a way to set that scrollerId
(a simple public method works).
Note another way is if you are using a ScrollView
for vertically scrolling elements with ViewPager
children, you'll need to go a different direction. Have a subclass of ScrollView
that detects vertical scrolling directions and bails for horizontal scrolling so the ViewPager
picks it up.
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
xDistance = yDistance = 0f;
lastX = ev.getX();
lastY = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
final float curX = ev.getX();
final float curY = ev.getY();
xDistance += Math.abs(curX - lastX);
yDistance += Math.abs(curY - lastY);
lastX = curX;
lastY = curY;
if (xDistance > yDistance)
return false;
}
return super.onInterceptTouchEvent(ev);
}
Upvotes: 9