Implementing ViewPager2 in a basic Android app
I’ve only been learning Android for the last 6 months or so, in my spare time, so this is 1st in a series of quick blog posts on implementing some features in an Android app. These will be fairly basic for most experienced people, but helped me and maybe help other new devs with getting to grips with these things.
You can find the code in a GitHub repo
ViewPager2
ViewPager allows us have a horizontal (and vertical) swiping component that populates from a series/list of various kinds, either Views, Fragements or data sources. ViewPager2
is built on RecyclerView
, which gives us some improvements around performance, rtl support, and it means when we’re familiar with one, we’re mostly familar with the other. We can also add fancy animations as we swipe.
This is what we’ll be building
Basics & intro
This is not by any means comprehensive, but is from my perspective, ViewModels retrieve data from repositories, fragments observe the ViewModel’s data and apply an adapter against them, an Adapter converts the data from the ViewModel into something that can be bound to the individual ViewHolders, and this is what updates the UI when we swipe. We use databinding to to do a lot of the heavy lifting for us.
Getting started
We’re using the latest Android studio beta, but the latest stable Android studio should work fine. We create a new project with an empty activity to get started.
First we want to enable data binding in the app
Add this into the gradle file of your app module
buildFeatures {
dataBinding = true
}
and we need to apply kapt plugin for databinding
apply plugin: "kotlin-kapt"
and then further down we add a dependency on the viewpager2 module, we also include lifecycle-extensions to remove a few deprecated statements
implementation "androidx.viewpager2:viewpager2:1.0.0"
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
We then create a package to represent the data we want to use, in my example case testimonials, within that package a kotlin class called TestimonialAdapter
, this will extend a ListAdapter
inorder to bind a testimonial data object to the layout, we’ll fill this out a bit more later.
Alongside this we create a package called datasource
and inside this a Testimonial
class and a TestimonialRespository
class, these are fairly simple, and in the repository we’ll just return some pre-defined objects rather than getting bogged down in network or databse requests.
Data data data
Infrastructure
Next we’re going to create a view to represent the testimonial and a fragement/viewmodel to hold them and give them some context.
Create a new toplevel package ui, and within that a package home, and then create a new fragment (with viewmodel) within that.
- app/
- testimonials/
- TestimonialAdapter
- datasource/
- Testimonial
- TestimonialRepository
- ui/
- home/
- HomeFragment
- HomeViewModel
- home/
- testimonials/
And then within out layouts folder we want
- layout
- home_fragment
- testimonials_layout
- testimonial_layout
- activity_main
So far we’ve covered the Testimonial
data class and TestimonialRepository
class, we’re going to switch focus for a bit and look at our layout files.
Layout files
Our testimonial_layout
is a simple file that binds with the Testimonial object uses TextViews to output the data contained within the individual Testimonial
, this is the layout that the ViewPager uses, and to which we bind the individual Testimonial
objects
and the testimonials_layout
is the container for our ViewPager2
Our home_fragement
is a lot smaller and is just there as a wrapper around the testimonials_layout
and we also need to update our activity_main
layout to render our fragment, normally we’d be using the navigation or something, but this is just a simple app so we can do it like this
So we’ve covered the layouts, the Testimonial
data class and the TestimonialRepository
- app/
- testimonials/
- TestimonialAdapter
- datasource/
- Testimonial ✅
- TestimonialRepository ✅
- ui/
- home/
- HomeFragment
- HomeViewModel
- home/
- testimonials/
- layout
- home_fragment ✅
- testimonials_layout ✅
- testimonial_layout ✅
- activity_main ✅
Now to wrap up the rest of the binding of the data to the layout, starting with the HomeViewModel, this just gets the repository of testimonials and stores them to be used in the layout
Now we’re down to the couple of classes that do most of the heavy lifting, the adapter and the fragment
We create TestimonialAdapter
that extends the ListAdapter
, this already gives us a few things to make development easier, but we do have to implement our own DiffUtil.ItemCallback
for it. The override of onCreateViewHolder
is so we can use databinding to bind the the data into the viewholder, our override of onBindViewHolder
is so we can bind the correct testimonial to the viewholder and we override getItemViewType
so that list/viewholder knows what layout is needed to inflate/populate.
The TestimonialViewHolder
takes in the data binding and when the adapter passes the testimonial to the viewholder we trigger the binding to update the variable in the layout.
Here we have the final piece of the app, the HomeFragment
, here we hold the HomeViewModel
and the TestimonialAdapter
, when we create the view (onViewCreated
) we set up all our binding mechanics.
Then in onActivityCreated
we observe the LiveData List of Testimonials that’s in the ViewModel and when it changes we apply the TestimonialAdapter to it, so that it’s able to bind correctly to our view
- app/
- testimonials/
- TestimonialAdapter ✅
- datasource/
- Testimonial ✅
- TestimonialRepository ✅
- ui/
- home/
- HomeFragment ✅
- HomeViewModel ✅
- home/
- testimonials/
- layout
- home_fragment ✅
- testimonials_layout ✅
- testimonial_layout ✅
- activity_main ✅
Now that it’s complete, once we build and run this we’ll get an app with a swipeable section as you can see in the gif below!
You can find the code in a GitHub repo
I’m very concsious that we’ve skipped any form of testing for this, I don’t know much about testing in Android, but I have the creepy feeling of my bestie, Maja, breathing down my neck at the lack of them.
Next I’ll be writing:
- writing tests for ViewPager
- a quick post about repositories
- maybe one on different animations in ViewPager
- Annotations and BindingAdapaters (glide, extra formatting or styling)