Android

Combining the Android ViewPager widget and the ActionBar Fragment tabs

Kyle Miller describes how he combined the Android ViewPager widget and the ActionBar Fragment tabs to create a UI that would allow a user to swipe through tabs.

When Samsung and Google unveiled Ice Cream Sandwich (ICS) and the Galaxy Nexus in October 2011 at an event in Hong Kong, Matias Duarte, Google's Director of the Android User Experience, introduced some of ICS's new features and explained some of the UI/UX enhancements. A big change that resonated with me was that Google fully embraced the gesture of swiping left and right and tried to incorporate it everywhere possible throughout the OS.

After using ICS for almost two months, I can attest that Google did a great job of scattering this gesture throughout the OS, and that it helps unify the UX. Google even did this in many of its native applications, which makes you feel like you intuitively know when you're using a Google application. These are some of the places I have noticed the use of this gesture:

  • Home Screen
  • Switching panels in the App/Widget Drawer
  • Dismissing notifications in the Notification Tray
  • Closing apps in the Multitasking view
  • Closing browser tabs
  • Switching between views in your Stream on Google+
  • Switching between emails in Gmail
  • Switching between views in the Market
  • Switching between conversations in Google Talk

I was most impressed with the implementations of Google+ and the Market, where you can swipe between Views and the labels above the views swipe with the View but in a separate, disconnected manner. It's difficult to explain, so I encourage you to take a look for yourself.

I decided to try to incorporate this UX into my applications because, if users understand how to use this gesture in other native Google applications, it should be natural and intuitive in mine. I remembered a blog post on the Android Developer Blog that talked about a ViewPager widget from the Android Compatibility Library, which is the same widget Google used to build the Market UI and very likely the Google+ UI. A cool aspect of the ViewPager widget is that you can use it to page through Views or Fragments. And, the ActionBar in Honeycomb and ICS can be used to form a tabbed navigation with Fragments.

Then I decided to try and combine these two concepts to create a UI that would allow the user to swipe through tabs. It turns out it wasn't terribly difficult to combine the FragmentPagerSupport and ActionBar Tab Navigation examples.

Combining concepts

First, I implemented both concepts in the same app; this step was quite simple. When that was done, I had tabs that controlled one set of Fragments and another set of swipe-able Fragments below.

Then, I realized that I would have to get rid of the set of Fragments controlled by the tabs and allow the tabs to control the Fragments in the ViewPager. Similarly, the ViewPager would have to be able to control which tab was currently selected, to allow for multiple forms of navigation.

Eliminating the tabs' Fragments

In order to eliminate the Fragments in the tabs, I modified the TabListener class from the ActionBar Tab Navigation example. I began by modifying the constructor to allow for a reference to the ViewPager to be passed in. Then, I changed the onTabSelected method to call setCurrentItem on the ViewPager that was passed into the constructor. I realized that as long as I passed in the index of the tab as the "tag" to the TabListener constructor, even though it was a string, I could parse an int from the tag and pass that to setCurrentItem. Next, I commented out the existing code in onTabUnselected, since it was no longer needed.

Controlling the tabs from the ViewPager widget

The last thing to complete was to enable the ViewPager widget to set the currently selected Tab whenever the Fragments were paged. I tried to modify the getItem method of the FragmentPagerAdapter; however, because this method is called immediately when the FragmentPagerAdapter loads, it was causing problems unless the Tabs had been initialized. I wasn't happy with this caveat, so I dug a little deeper and found the OnPageChangeListener class, which can be set for the ViewPager widget. Specifically, the onPageSelected method of the OnPageChangeListener will be called when the Fragments are paged, which was the easiest place to set the tab states. By calling the getTabAt method on the activity's ActionBar, passing the index that was passed to onPageSelected, you could then call the select method on the tab returned.

Get the source code

I uploaded all of the source code for this project to GitHub. Please feel free to download or browse it. If you make any interesting modifications to code, I'd love to see what you come up with, so let me know in the discussion.

About

Kyle is a senior software engineer specializing in web/Android development living in Austin TX. He's a self-professed "gadget freak" whose passion for mobile devices drove him to jump into the mobile industry in 2010. He enjoys the fast-paced nature ...

3 comments
droidb
droidb

Great article Kyle ! I was swimming in your code, it's very clear. I would like to ask you how to do it if we have different fragments for each tab, if you know. I have three tabs with each fragment, everyone very complex. Thanks in advance.

alfa_bet
alfa_bet

To answer my own question, yes it does!