An Introduction to ViewPager2

Photo by Brandi Redd on Unsplash

Background

Designers have often wanted to allow a user to flip through content horizontally with the opportunity to focus on each page but quickly navigate through many pages. This is often used for tabbed views, viewing photos, onboarding flows within apps. To help developers implement this, Android provided the ViewPager view. While developers have continually used it in apps, the ViewPager has had many issues which may have made it difficult to work with. It presents issues such as lacking difficulty updating content, modifiable Fragments, Right-to-Left language support, and vertical swiping.

Last week, Google released an alpha version of the updated ViewPager view which aims to provide a solution to these issues.

Digging In

In this example, we’ll be building a single activity app with a ViewPager2 and some buttons along the top to allow a user to edit the content at run time. The user will be able to navigate to the beginning or end, add and delete a page. We’ll be using a ViewModel to store this data away from the Activity.

Developers familiar with the RecyclerView will have no trouble adopting the new ViewPager2 APIs. While the ViewPager2 extends from a ViewGroup, it carriers a RecyclerView under the hood. To provide data to the view, find the ViewPager2 in your layout and set the adapter.

As you can see, we’re providing the structure for each of the pages through:

  • onCreateViewHolder to inflate our view and store it in a holder
  • getItemCount to retrieve the number of items from our ViewModel
  • onBindViewHolder to assign the data to the view

In addition, our ItemHolder class exists to find and properly bind the data to the TextView.

At this point, we should be in good shape to run our code!

This is great! We’re already up and running and efficiently showing pages of content. Out of the box, the ViewPager2 implementation already supports users who use a language which read Right to Left. In addition, if the design called for vertical swipes instead of horizontal swipes, it’s a one line change:

viewPager.orientation = ViewPager2.ORIENTATION_VERTICAL

To update content, we can wire up a few buttons to adjust our data in our ViewModel and notify the adapter of the appropriate changes.

And voilà!

As of this version, the ViewPager2 view only has a handful of public methods for configuring the behavior of the view. As we’ve seen, we can provide data via the adapter, but we can also configure:

  • setCurrentItem to specify a new item to display
  • registerOnPageChangeCallback / unregisterOnPageChangeCallback to listen for when the page is changed
  • setPageTransformer which may be the most interesting. By using this method, you are able to specify the property animation which will be used when the page is swiped

Under the Hood

How does this all work? As we noted earlier, the ViewPager2 class extends from a ViewGroup, similar to the original implementation. However, this implementation depends on a RecyclerView, a LinearLayoutManager and a PagerSnapHelper to transition the content. Care has also been taken by overriding the onViewAdded method to ensure that developers do not add custom Views into the ViewGroup.

The PagerSnapHelper handles the heavy lifting of understanding the users gestures by implementing the RecyclerView.OnFlingListener. When initializing the ViewPager2, it the PagerSnapHelperto the RecyclerView and registers the appropriate listeners. The RecyclerView.fling() provide velocity for the X and Y gestures and provide them to the SnapHelper.onFling implementation determine if the user is just swiping, or if they have exceeded the “fling” velocity. If they have “flung” the view, they will proceed to the next item, otherwise it’ll settle back to the currently selected item.

Within the onMeasure and onLayout methods of the ViewPager2 handle the work to ensure the RecyclerView is matching the entire parent of the view. The onSavedInstanceState and matching restoreInstanceState methods will do the dirty work to ensure the view is properly saved and restored across orientation changes.

Up Next

Since this is an early alpha release, we can expect more updates in the months as we head towards I/O 2019. These updates will most likely continue to build out functionality while knocking out a few outstanding bugs. Google has already acknowledged issues with clipToPadding, offscreen limit control, integration with TabLayout and more (see Known Issues).

For the complete project used in this post, check out the GitHub repo at https://github.com/chris-mitchell/viewpager/

Links

Documentation — https://developer.android.com/reference/androidx/viewpager2/widget/ViewPager2

Samples — https://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/samples/ViewPager2Demos/src/main/java/com/example/androidx/viewpager2

Known bugs — https://issuetracker.google.com/issues?q=viewpager2