Tuesday, August 23, 2011

Horizontal View Swiping with ViewPager

[This post is by Rich “geekyouup” Hyndman, inspired by the fact that life just got that little bit easier — Tim Bray]

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, such as the new Android Market, Google Docs and Google+. 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(View collection, int position) {
View v = layoutInflater.inflate(...);
...
((ViewPager) collection).addView(v,0);
return tv;
}

@Override
public void destroyItem(View 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.

If you are launching an app onto Android Market that uses ViewPager then please ping me on Google+ or Twitter, I’d love to see how widely it is being used and the innovative scenarios in which it appears.


No comments:

Post a Comment