A simple Android example of implementing tabs using PagerTabStrip with ViewPager.
The release of Android
API
level 21 (Lollipop) deprecated a number of APIs
— in particular, anything to do with ActionBar tabs.
This means a common way of implementing tabbed navigation is now
discouraged, but things have not been particularly clear as to what
replaces these deprecated APIs. Of course, deprecated doesn’t mean
unusable. Deprecated though they are, ActionBar tabs will still work.
But anyone starting a new long term Android project might reasonably baulk
at firing up the Android Studio “New Project” code wizard only to be
greeted with a whole lot of deprecation warnings in the generated code for
anything with tabs. Even if the resulting code does actually work. For now.
So what are our options if we want tabs, but don’t want to use any of these
deprecated APIs?
Roll your own tabs implementation
(Obviously not helpful to any developers dealing with onerous deadlines.)
Use a third party implementation.
Incorporate or adapt the implementation of tabs in either the Android
SDK
Sliding Tabs sample
or
the Google
iosched
app.
Use the venerable
PagerTabStrip
.
Use
TabLayout
from Google’s newish
Android Design Support Library
.
I’ll explore the last two options in this tutorial. In this post I’ll show
a simple implementation of tabs using
PagerTabStrip
. In the next post I’ll
look at
TabLayout
.
PagerTabStrip works in conjunction with
ViewPager
,
and plays well with
AppCompatActivity
(although the results aren’t exactly Material Design friendly).
For this example project we’ll use
AppCompatActivity
as our Activity class,
and
Theme.AppCompat.Light.DarkActionBar
as the application theme.
We’ll start with the layout for our activity
(
activity_pager_tab_strip.xml
), which in this case will just be a
ViewPager
containing a
PagerTabStrip
:
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="net.voidynullness.android.tabitytabs.PagerTabStripActivity">
<android.support.v4.view.PagerTabStrip
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"/>
</android.support.v4.view.ViewPager>
The layout_gravity is set to “top” so that the tabs are displayed at the top of
the ViewPager.
The activity code (PagerTabStripActivity.java) is fairly straightforward:
package net.voidynullness.android.tabitytabs;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
public class PagerTabStripActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pager_tab_strip);
TabsPagerAdapter adapter = new TabsPagerAdapter(getSupportFragmentManager());
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(adapter);
There’s not much going on in the Activity — it’s basically just
configuring the ViewPager by giving it a suitable adapter object. In
this case the adapter class is TabsPagerAdapter, which is our subclass of
FragmentPagerAdapter
(see below). Notice that we need to pass a FragmentManager to the
adapter, and here we’re passing the support library fragment manager, since
we’re using AppCompatActivity.
TabsPagerAdapter is a subclass of FragmentPagerAdapter, and it’s
here that the fragments corresponding to each tab page are instantiated,
and tab title text is defined (TabsPagerAdapter.java):
package net.voidynullness.android.tabitytabs;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
@Override
public Fragment getItem(int position) {
return PageFragment.newInstance(position + 1);
@Override
public int getCount() {
return 3;
@Override
public CharSequence getPageTitle(int position) {
return "TAB " + (position + 1);
It’s about as minimal as a FragmentPagerAdapter can be. At the very
least, subclasses of FragmentPagerAdapter must implement getItem()
and getCount().
getItem() is expected to return the fragment for the specified
position. Internally,
FragmentPagerAdapter calls getItem() to instantiate
fragments, and uses the FragmentManager passed into the constructor to
manage these fragments.
getCount() should return the total number of fragments.
We’re also overriding getPageTitle(), which is used to set the text for
each tab position.
So we have our ViewPager and FragmentPagerAdapter, now we need a
fragment to actually display something. We’ll call our simple placeholder
fragment class PageFragment. It will just display a text string on
the screen to indicate which fragment “page” is currently selected
(PageFragment.java):
package net.voidynullness.android.tabitytabs;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class PageFragment extends Fragment {
private static final String ARG_PAGE_NUMBER = "page_number";
public PageFragment() {
public static PageFragment newInstance(int page) {
PageFragment fragment = new PageFragment();
Bundle args = new Bundle();
args.putInt(ARG_PAGE_NUMBER, page);
fragment.setArguments(args);
return fragment;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_page_layout, container, false);
TextView txt = (TextView) rootView.findViewById(R.id.page_number_label);
int page = getArguments().getInt(ARG_PAGE_NUMBER, -1);
txt.setText(String.format("Page %d", page));
return rootView;
The newInstance() idiom
of a static factory method is used to create and initialise new fragments.
As shown above, our fragment adapter (TabsPagerAdapter) creates
PageFragment fragments by calling the static newInstance() method
and passing in the page/tab number of that particular instance.
Inside newInstance(), the page number is saved as an argument bundle.
In onCreateView(), the TextView contents are updated to display the
page number, which is retrieved from the arguments.
The corresponding layout file for our PageFragment class simply
contains a single TextView to display the page number
(fragment_page_layout.xml):
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="net.voidynullness.android.tabitytabs.PageFragment">
<TextView android:id="@+id/page_number_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@android:style/TextAppearance.Large"
android:gravity="center"
android:layout_centerVertical="true" />
</RelativeLayout>
The result is three fragments, that can be switched by swiping or selecting the
appropriate tab:
The complete source code for this example is on BitBucket.
In the next post,
I’ll take a look at an alternative to PagerTabStrip — TabLayout
from the Android Design Support Library — which provides similar
functionality but is more in keeping with Material Design conventions.
Related Posts:
How to use TabLayout
Australia.
I do mostly coding, and sometimes blogging, and here I mostly blog about coding, when not
going off on weird tangents.
More about me.