Nov 5, 2012

Examining the ViewPager #3

This article is part of a series of articles about the ViewPager component. Click here to see a list of all articles of this series.

Horizontal scrolling pages

Have you ever tried putting horizontal scrolling components inside a ViewPager? Well, since revision 9 of the support library this is supported by the ViewPager. As long as the inner component can scroll horizontally this component will be scrolled. Whenever the component can't be further scrolled the ViewPager will handle the touch events and you start to switch to the next page. This works out-of-the-box for scrolling view components of Android like the WebView.

Internally the ViewPager uses ViewCompat.canScrollHorizontally(View v, int direction) to determine if a child view can be scrolled horizontally and should receive the according touch events. Unfortunately this method is only implemented for Android 4.0 (API level 14) and above. For all earlier versions this method will always return false and therefore never scroll the components inside the ViewPager.

Bezel swipe

Allowing horizontal scrolling components introduces a new problem: What if you want to switch pages but not scroll every component to its horizontal end? When you start the swipe at the phone's bezel (or actually from the edge of the ViewPager) you'll switch pages instead of scrolling the page's content. This gesture is called bezel swipe.

For reading more about the bezel swipe gesture from a UI point of view read "Bezel swipe, a Solution to Pan and Swipe Confusion?" on Android UI Patterns.

The good news is again: The ViewPager supports bezel swipe out of the box. But as you can't horizontally scroll inside pages on devices running an Android version lower than 4.0 (API level 14) bezel swipe isn't of any use on these as well.

The area to start a bezel swipe has a width of either 16dp or a 10th of the total width of the ViewPager depending on which one is smaller.


Fake dragging

The ViewPager supports fake dragging. Fake dragging can be used to simulate a dragging event/animation, e.g. for detecting drag events on a different component and delegating these to the ViewPager.

You have to signal the ViewPager when to start or end a fake drag by calling beginFakeDrag() and endFakeDrag() on it. After starting a fake drag you can use fakeDragBy(float) to drag the ViewPager by the given amount of pixels along the x axis (negative values to the left and positive values to the right).

The following example uses a SeekBar whose current progress state is used to fake drag a ViewPager by the given percentage.

SeekBarPagerListener.java

This video shows the fake drag in action: