An Introduction to ViewPager2
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.
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
- onBindViewHolder to assign the data to the view
In addition, our
ItemHolder class exists to find and properly bind the data to the
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.
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:
setCurrentItemto specify a new item to display
unregisterOnPageChangeCallbackto listen for when the page is changed
setPageTransformerwhich 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
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
PagerSnapHelper handles the heavy lifting of understanding the users gestures by implementing the
RecyclerView.OnFlingListener. When initializing the
ViewPager2, it 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.
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.
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/
Known bugs — https://issuetracker.google.com/issues?q=viewpager2