An Introduction to ViewPager2
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 displayregisterOnPageChangeCallback
/unregisterOnPageChangeCallback
to listen for when the page is changedsetPageTransformer
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 View
s 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 PagerSnapHelper
to 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
Known bugs — https://issuetracker.google.com/issues?q=viewpager2