Note: This post is sort of a continuation of my previous post on ViewPager
and its related pager adapters with tabs.
When working with ViewPager
we most likely include action bar tabs and integrate them with their corresponding screens in the ViewPager
. Action bar tabs works great but just incase if you prefer scrollable tabs and want to use them over action bar tabs then there are two ways to achieve that:
What's the one thing every developer wants? More screens! Enhance your coding experience with an external monitor to increase screen real estate.
Both of them are supposed to be used as a child view of the ViewPager
widget in the XML layout resource. So here’s how a ViewPager
with a PagerTabStrip
in it would look like in the layout file:
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v4.view.PagerTabStrip android:id="@+id/pager_tab_strip" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:background="#33b5e5" android:textColor="#fff" android:paddingTop="5dp" android:paddingBottom="5dp" /> </android.support.v4.view.ViewPager>
Similarly, this is how the layout code for a ViewPager
with a top-aligned PagerTitleStrip
would be like:
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v4.view.PagerTitleStrip android:id="@+id/pager_title_strip" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:background="#33b5e5" android:textColor="#fff" android:paddingTop="5dp" android:paddingBottom="5dp" /> </android.support.v4.view.ViewPager>
Not much of a difference in the code between both the versions. Only the tag name and ID got changed.
Now when you test this code in your emulator or a physical android device, then you’ll notice a blue strip at the top of the view pager. You’ll be able to navigate through the pager screens but there won’t be any text in the pager strip unless they’re specified in the getPageTitle()
method of the pager adapter implementation which should return the title for specific pages. The method implementation should look something like this:
@Override public CharSequence getPageTitle(int position) { switch (position) { case 0: return "Tab One"; case 1: return "Tab Two"; case 2: return "Tab Three"; } return null; }
The method should return null
which would indicate no title for that particular page. Although I used switch
block you could also write the same code in another way by using arrays and returning the corresponding title by using the position
argument as the array index.
Code Sample
For the sake of quickly testing `PagerTabStrip` I’ve put together some code. Here’s the Activity bit:
public class MainActivity extends Activity { CustomPagerAdapter mCustomPagerAdapter; ViewPager mViewPager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mCustomPagerAdapter = new CustomPagerAdapter(getFragmentManager(), this); mViewPager = (ViewPager) findViewById(R.id.pager); mViewPager.setAdapter(mCustomPagerAdapter); } class CustomPagerAdapter extends FragmentPagerAdapter { Context mContext; public CustomPagerAdapter(FragmentManager fm, Context context) { super(fm); mContext = context; } @Override public Fragment getItem(int position) { // Create fragment object Fragment fragment = new DemoFragment(); // Attach some data to the fragment // that we'll use to populate our fragment layouts Bundle args = new Bundle(); args.putInt("page_position", position + 1); // Set the arguments on the fragment // that will be fetched in the // DemoFragment@onCreateView fragment.setArguments(args); return fragment; } @Override public int getCount() { return 3; } @Override public CharSequence getPageTitle(int position) { return "Page " + (position + 1); } } class DemoFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout resource that'll be returned View rootView = inflater.inflate(R.layout.fragment_demo, container, false); // Get the arguments that was supplied when // the fragment was instantiated in the // CustomPagerAdapter Bundle args = getArguments(); ((TextView) rootView.findViewById(R.id.textView)).setText("Page " + args.getInt("page_position")); return rootView; } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.gesture, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
This is how the res/layout/activity_main.xml
should be like:
<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" android:id="@+id/relativeLayout"> <android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v4.view.PagerTabStrip android:id="@+id/pager_title_strip" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:background="#33b5e5" android:textColor="#fff" android:paddingTop="5dp" android:paddingBottom="5dp" /> </android.support.v4.view.ViewPager> </RelativeLayout>
Finally here’s the res/layout/fragment_demo.xml
:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="New Text" android:id="@+id/textView" /> </LinearLayout>
Go ahead and test your app now! Play with the view pager and its top-aligned pager strip. You can also customize the PagerTabStrip
programatically. Feel free to go through the public methods here.
PagerTabStrip vs PagerTitleStrip – the Difference
Although both of them are quite similar there are certain differences which makes PagerTabStrip
superior compared to the other one and hence most likely you’ll always want to use it over the other.
PagerTitleStrip
only indicates the section we’re in through the title names. On the contrary, PagerTabStrip
not only indicates the section name but also has the tab indicator (bottom border) that depicts the active tab. Also PagerTabStrip
is interactive which means you can click on the tabs to switch among screens while you cannot do that with PagerTitleStrip
(major limitation IMHO).
On going through the public methods for both in the docs, you’ll notice PagerTabStrip
has marginally more methods or options to customize compared to PagerTitleStrip
.
I came across this plugin called ViewPagerIndicator that allows you to customize your pager strip in so many different ways. You can even replicate the google play scrollable tabs with this plugin.
Hope that helps!