What ViewPager2 has to offer?

Dilpreet Singh
TechShots
Published in
4 min readMar 5, 2019
Photo by Enrico Mantegazza on Unsplash

ViewPager helps to display screens in swipeable format but ViewPager has its limitations such as lack of Right-to-Left Layout, Vertical Swiping, and difficulty in notifying about updates. In order to overcome these limitations, Google released the alpha version of ViewPager2 on 7th Feb 2019. Before digging deep into how ViewPager2 is different ViewPager lets have a look at how to use it.

Setting Up

Make sure your project is migrated to AndroidX. Add viewpager2 dependency in your app build.gradle file.

dependencies {
implementation 'androidx.viewpager2:viewpager2:1.0.0-alpha01'
}

Next, add ViewPager2 widget to your layout file.

<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

ViewPager2 needs an adapter. For this, we can either use RecyclerView.Adapter or FragmentStateAdapter which supports fragment out of the box. We will use FragmentStateAdapter for now.

class UserAdapter(private val userList: ArrayList<String>,                fragmentManger: FragmentManager): FragmentStateAdapter(fragmentManger) {    override fun getItem(position: Int): Fragment {
return UserFragment.getInstance(userList[position])
}
override fun getItemCount(): Int {
return userList.size
}
}

Now we need to create a fragment which our Adapter will use. We will pass a name to UserFragment as an argument.

class UserFragment : Fragment() {
private var mUserView: TextView? = null
companion object
{
fun getInstance(name: String): Fragment {
val fragment = UserFragment()
val arg = Bundle()
arg.putString("name", name)
fragment.arguments = arg
return fragment
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_user, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mUserView = view.findViewById(R.id.user_name)
val name = arguments?.getString("name")
mUserView?.text = "Hello $name"
}
}

The last step is to attach the adapter to our viewpager2 earlier.

class MainActivity : AppCompatActivity() {    override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val viewPager = findViewById<ViewPager2>(R.id.view_pager)
val userList = arrayListOf("John", "Doe", "Foo", "Bar")
viewPager.orientation = ViewPager2.ORIENTATION_HORIZONTAL
viewPager.adapter = UserAdapter(userList, supportFragmentManager)
}
}

How’s ViewPager2 different from ViewPager?

ViewPager Minimalistic BluePrint

ViewPager acts as a manager controlling the insertion, updation or deletion of views or fragments by commanding the PagerAdapter.
So, FragmentStatePagerAdapter and FragmentPagerAdapter contain the logic for managing state and adding view or fragment to the ViewGroup i.e. the ViewPager.

ViewPager2 Minimalistic BluePrint

ViewPager2 comes with a RecyclerView under the hood and it delegates this responsibility to RecyclerView.
ViewPager2 API comes with a FragmentStateAdapter which is similar to what FragmentStatePagerAdapter offers i.e. saving the state of the fragment and destroying fragment’s view when pages are not visible to the user.

Internals of FragmentStateAdapter

As RecyclerView.Adapter needs a ViewHolder, ViewPager2 API uses
FragmentViewHolder which is supplied with a FrameLayout as a container view in onCreateViewHolder and also has a fragment as a class member which is not used during initialization of the viewholder.

Our fragment at position x is attached to the ViewHolder’s fragment in onBindViewHolder and is detached when the view is recycled where viewholder.fragment is set to null so that the ViewHolder with a FrameLayout could be used by another fragment thus reusing the views by attaching and detaching the fragments to the viewholder without destroying them along with saving and restoring the state of the fragment.

ViewPager2 supports Horizontal and Vertical scrolling

viewPager.orientation = ViewPager2.ORIENTATION_HORIZONTAL
or
viewPager.orientation = ViewPager2.ORIENTATION_VERTICAL

registerOnPageChangeCallback replaces addPageChangeListener

ViewPager provided with ‘addOnPageChangeListener’ for listening to scroll or page change events where we had to implement three methods and used only one or two.

viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {

}

override fun onPageSelected(position: Int) {

}

override fun onPageScrollStateChanged(state: Int) {

}
})

ViewPager2 comes with ‘registerOnPageChangeCallback’ where it allows to override the method of our choice thus removing unused functions.

viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
}
})

--

--