23 August 2011
Updated Dec 12 2012
It has been over a year since the ViewPager
launched and in that time it’s been used by many developers to improve the user experience of their applications. Over the year the APIs have been updated, adding some new features and deprecating some old method signatures.
Five methods in PagerAdapter
have been deprecated in order to switch from using View
in the method signature to using ViewGroup
. This makes it more obvious what the parameter refers to, improves the readability of the code and removes the need to constantly cast the Views to ViewGroups.
Some official ViewPager
resources have also been added:
A few ViewPager
hints that are worth mentioning as they keep recurring are:
setOffscreenPageLimit(2)
you’ll allow all of your pages to stay in memory all the time. This is a trade off between performance and memory considerations, so it is a good idea to listen for low memory warnings and be prepared to remove edge pages if necessary.Views
in your ViewPager
, it isn’t enough just to change the data set behind the adapter and call notifyDataSetChanged()
. You also need to ensure that you’ve correctly implemented getItemPosition(Object object) and return POSITION_NONE for items that have changed and return POSITION_UNCHANGED or the actual position for items that haven’t changed.setPageMargin()
and setPageMarginDrawable()
, allowing you to easily separate your pages.Here’s to the next year of paging views. The updated original post follows...
Whether you have just started out in Android app development or are a veteran of the craft, it probably won’t be too long before you’ll need to implement horizontally scrolling sets of views. Many existing Android apps already use this UI pattern. ViewPager standardizes the implementation.
ViewPager was released as part of the Compatibility Package revision 3 and works with Android 1.6 upwards. After following the instructions to obtain the package you can right-click on your Android project in Eclipse, choose ‘Android Tools’ and ‘Add Compatibility Library’, making the new classes available.
ViewPager is a ViewGroup and works in a similar manner to AdapterViews (like ListView and Gallery) so it shouldn’t feel too foreign. Note that if you use ViewPager in an xml layout, be sure to use the full class reference, e.g.
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"
… />
ViewPagers source their views from PagerAdapters which give you have full control over the reuse and recycling of the views. A PagerAdapter implementation called FragmentPagerAdapter is provided to facilitate the use of Fragments in a ViewPager; This is immensely powerful and as simple as implementing getCount() and getItem(). There is a sample called Fragment Pager Support provided in the Support Demos to illustrate this.
public static class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
@Override
public int getCount() {
return NUM_ITEMS;
}
@Override
public Fragment getItem(int position) {
return ArrayListFragment.newInstance(position);
}
}
FragmentPagerAdapter will detach each fragment as you swipe through the list, but keep them in memory so they can simply be reattached when the user swipes back. If you have a larger number of Fragments, the FragmentStatePagerAdapter is worth considering as it will remove them, with the downside being they need to be rebuilt as the user swipes back to them. So, if you have fewer, more complex fragments the FragmentPagerAdapter makes sense, but consider FragmentStatePagerAdapter for larger sets.
On the more simplistic side I recently wrote a ViewPager/PagerAdapter example that serves up simple TextViews. One thing to note is that if you are implementing your own PagerAdapter it is up to you, the developer, to add and remove your views to and from the ViewGroup. To facilitate this the ViewPager is passed into the PagerAdapter methods instantiateItem() and destroyItem().
@Override
public Object instantiateItem(ViewGroup collection, int position) {
View v = layoutInflater.inflate(...);
...
((ViewPager) collection).addView(v,0);
return v;
}
@Override
public void destroyItem(ViewGroup collection, int position, Object view) {
((ViewPager) collection).removeView((TextView) view);
}
The source code for ViewPager is also included and available in <android-sdk>/extras/android/compatibility/v4/src. It is worth checking as you can generate the reference documentation from it using Javadoc. In the reference docs / source you’ll find other useful methods, for example setOnPageChangeListener(), which enables your application to track which View is currently visible.