ViewPager with gradual Background Transition
Recently I came across one of those tutorial screens in a newly installed app. It would be quite ordinary use of the Android’s ViewPager
if not for a smooth gradual background change while swiping between pages.
I searched the web but couldn’t find a nice solution anywhere, so I set off to create a solution of my own.
What are we creating
Before we dive into code, let’s show off the finished effect (the source and sample apk can be found at the bottom of the article):
</img>
As you can see, the background of the ViewPager
animates gradually, so you can’t see the edges of adjacent views.
The basics
First we have to set up an Activity
(in my case FragmentActivity
for compatibility) with a ViewPager
.
SectionsPagerAdapter
is just a class extending the FragmentPagerAdapter
which provides the ViewPager
with placeholder fragments for each page.
Changing the background
Now that we have set up the foundation for out project, we can move on to actually changing the background of the ViewPager
.
Changing the color is a matter of one method call:
The only remaining problems are:
- Determining the right color of the background while swiping if we know the color of Page A and the color of page B.
- Updating the background color while swiping.
Solution #1 - using the ValueAnimator
To determine the right color, which is a blend of Color A and Color B, I at first decided to use the ValueAnimator
of ArgbEvaluator
object.
ValueAnimator
does all the job of calculating the correct color over time for you. You only have to pass the colors you want to iterate over - in my case 3, because my SectionsPagerAdapter
returns only 3 pages.
To change the background of the ViewPager
each time the animation updates, we have to set a listener.
And at last, we set the duration of our animation:
To explain the magic number 10000000000l, setDuration()
method only accepts a long
value, where as we’re going to be working with float
values while calculation the position of pages in the ViewPager
. To keep the precision, we will multiple the float values by this number, so that for instance number 0.9876543219 will be converted to 9876543219.
Normally when using ValueAnimator
you would set the duration and start the animation by calling ValueAnimator#start()
, but we’re only going to use the animator for determining the right color in each state of swiping between pages.
To calculate the color we need to know what is the ViewPager
currently showing. To do that we create our listener that implements ViewPager.OnPageChangeListener
.
In previous section we set the duration of the animation for 3 pages to 2 * 10000000000. Method onPageScrolled()
will recieve value for position parameter in a range of [0,3) and for positionOffset in [0,1) range.
An example: if position is 0 and positionOffset is equal to 0.98, it means that we’re swiping to/from second page and 98% of the first page is already hidden.
Therefore, by using the formula ((positionOffset + position) * 10000000000l)) we are moving on a timeline from 0 to 20000000000 (in this example).
The last step already showed in the code above is to call ValueAnimator#setCurrentPlayTime()
which will set the current position of the animation and will also trigger an animation update which will call our listener that will update our ViewPager
background.
Solution #2 - getting rid of the ValueAnimator
The ValueAnimator
’s use wasn’t at all necessary. Using ArgbEvaluator
directly will produce a cleaner code, but you’ll have to check for some boundary cases.
Each time we’re going to call ArgbEvaluator.evaluate()
, we’re going to need to pass the 2 colors we want to blend. That means we have to keep an array of all the colors;
Unlike in the first solution, we’ll set the color of the background right in the ViewPager.OnPageChangeListener
.
As you can see, we have to check for the last page to avoid OutOfBoundsException
. However we can skip all the hassle with converting floats to ints and setting the Animators length.
This approach will even work for cases where you supply an array with less colors than actual pages. For those pages the last color will always be set.
Sample App
If you’d like you can download a sample app to try the effect on your device.
Or view the source on GitHub.
Acknowledgements: In the sample app, PagerSlidingTabStrip was used for the ViewPager tabs.