My previous article explains about Android Tab Layout and it got very good ranking in search engines. But unfortunately TabHost is deprecated by android in favor of fragments. So it is suggested that use fragment to achieve tab layout.
This article shows you how to create tab layout using fragments and viewpager. Also you can swipe between tab view as it is the functionality of viewpager which is not possible when using TabHost.
Android Material Design Tab Layout
Although this article explains the Tab Layout in well detailed manner, lot of the methods used this article were deprecated. I strongly suggest check out the latest article Android Material Design Tabs (with Android Design Support Library) once you are done through this article.
ViewPager and Fragments
Before getting into this tutorial it is suggested to have knowledge on Fragments and ViewPager as these two are main concepts used here. Unfortunately I haven’t covered about fragements and viewpager on androidhive 🙁
Layout Overview
Checkout the following pic which explains the complete overview of layout architecture. Basically we are using ViewPager as main layout and for individual pager views we use Fragments. The tabs are part of Action Bar.
Creating new Project
Even though you are not familiar with ViewPager or Fragments, don’t worry. You will get an idea about what those are and how to use them once you are done through this article. So let’s start by creating a new project.
1. Create a new project in Eclipse from File ⇒ New ⇒ Android ⇒ Application Project. While creating the project select the app theme which has Action Bar as shown in the below image.
2. As we are going to use Fragments, extend your main activity from FragmentActivity. Also implement this class from ActionBar.TabListener as we are adding Tabs too.
public class MainActivity extends FragmentActivity implements ActionBar.TabListener {
3. Open main activity layout file and add ViewPager element. (My layout file for main activity is activity_main.xml)
<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.ViewPager>
4. I normally prefer to create a separate package for adapter classes just to separate them from activity classes. So create a new package named your_package_name.adapter. I named my new package as info.androidhive.tabsswipe.adapter
5. I am creating a FragmentPagerAdapter class to provide views to tab fragments. Create a class called TabsPagerAdapter.java under adapter package. This adapter provides fragment views to tabs which we are going to create them later in this tutorial.
package info.androidhive.tabsswipe.adapter; import info.androidhive.tabsswipe.GamesFragment; import info.androidhive.tabsswipe.MoviesFragment; import info.androidhive.tabsswipe.TopRatedFragment; 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 index) { switch (index) { case 0: // Top Rated fragment activity return new TopRatedFragment(); case 1: // Games fragment activity return new GamesFragment(); case 2: // Movies fragment activity return new MoviesFragment(); } return null; } @Override public int getCount() { // get item count - equal to number of tabs return 3; } }
Adding Tabs to Action Bar
6. In order to display tabs we don’t have to use any other UI element like TabHost. Action bar has the inbuilt capability of adding tabs. All we have to do is enable it using setNavigationMode(ActionBar.NAVIGATION_MODE_TABS) method. Open your MainActivity.java do the following.
Here I am adding three tabs Top Rated, Games, Movies to action bar. So I just stored all the tab names in a String array and added them to action bar using a for loop.
public class MainActivity extends FragmentActivity implements ActionBar.TabListener { private ViewPager viewPager; private TabsPagerAdapter mAdapter; private ActionBar actionBar; // Tab titles private String[] tabs = { "Top Rated", "Games", "Movies" }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Initilization viewPager = (ViewPager) findViewById(R.id.pager); actionBar = getActionBar(); mAdapter = new TabsPagerAdapter(getSupportFragmentManager()); viewPager.setAdapter(mAdapter); actionBar.setHomeButtonEnabled(false); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); // Adding Tabs for (String tab_name : tabs) { actionBar.addTab(actionBar.newTab().setText(tab_name) .setTabListener(this)); }
If you run the project, you can see the tabs displaying under action bar.
Adding Views for Tabs
We already returned respected fragments for tabs in the adapter class. To make it simple I am creating very simple layout for each tab and leaving it to you to build your own UI depending on your requirement. For now I just displayed a label in the view with some background color.
» First Tab View
7. The first tab I added is Top Rated. Create a new layout file under src ⇒ res folder named fragment_top_rated.xml and paste the following code.
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#fa6a6a" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:text="Design Top Rated Screen" android:textSize="20dp" android:layout_centerInParent="true"/> </RelativeLayout>
8. Also create respected Fragment activity class for this view. Create a new class named TopRatedFragment.java under your main package.
package info.androidhive.tabsswipe; import info.androidhive.tabsswipe.R; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class TopRatedFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_top_rated, container, false); return rootView; } }
» Second Tab View
The second tab in the list is Games. Just like above create a layout file and activity file for this tab.
9. Create a new layout file under src ⇒ res folder named fragment_games.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#ff8400" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:text="Design Games Screen" android:textSize="20dp" android:layout_centerInParent="true"/> </RelativeLayout>
10. Create a new class named GamesFragment.java with following code.
package info.androidhive.tabsswipe; import info.androidhive.tabsswipe.R; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class GamesFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_games, container, false); return rootView; } }
» Third Tab View
This third tab is Movies. This one need a layout file and activity class.
11. Create a layout file called fragment_movies.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#17df0d"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:text="Design Movies Screen" android:textSize="20dp" android:layout_centerInParent="true"/> </RelativeLayout>
12. Also create activity class for this view named MoviesFragment.java
package info.androidhive.tabsswipe; import info.androidhive.tabsswipe.R; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class MoviesFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_movies, container, false); return rootView; } }
Run the project and check whether the views for tabs are added or not.
And this is how it looks in landscape mode
Tab Change Listener
If you run the project you can see the swiping views working, but if you select a tab, view won’t change automatically. This is because ViewPager didn’t know about the tab change event. We have to manually change the view using Tab change listener.
13. In your MainActivity.java class add following code.
@Override public void onTabReselected(Tab tab, FragmentTransaction ft) { } @Override public void onTabSelected(Tab tab, FragmentTransaction ft) { // on tab selected // show respected fragment view viewPager.setCurrentItem(tab.getPosition()); } @Override public void onTabUnselected(Tab tab, FragmentTransaction ft) { }
View Change Listener
14. As well if you swipe the view, you can’t see respected tab selected. Here also using ViewPager setOnPageChangeListener() we have to select the respected tab manually.
/** * on swiping the viewpager make respective tab selected * */ viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageSelected(int position) { // on changing the page // make respected tab selected actionBar.setSelectedNavigationItem(position); } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageScrollStateChanged(int arg0) { } });
After adding these two listeners, if you run the project you can see everything working good.
Complete Code
Below is the complete code for MainActivity.java class
package info.androidhive.tabsswipe; import info.androidhive.tabsswipe.adapter.TabsPagerAdapter; import info.androidhive.tabsswipe.R; import android.app.ActionBar; import android.app.ActionBar.Tab; import android.app.FragmentTransaction; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.view.ViewPager; import android.view.Menu; public class MainActivity extends FragmentActivity implements ActionBar.TabListener { private ViewPager viewPager; private TabsPagerAdapter mAdapter; private ActionBar actionBar; // Tab titles private String[] tabs = { "Top Rated", "Games", "Movies" }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Initilization viewPager = (ViewPager) findViewById(R.id.pager); actionBar = getActionBar(); mAdapter = new TabsPagerAdapter(getSupportFragmentManager()); viewPager.setAdapter(mAdapter); actionBar.setHomeButtonEnabled(false); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); // Adding Tabs for (String tab_name : tabs) { actionBar.addTab(actionBar.newTab().setText(tab_name) .setTabListener(this)); } /** * on swiping the viewpager make respective tab selected * */ viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageSelected(int position) { // on changing the page // make respected tab selected actionBar.setSelectedNavigationItem(position); } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageScrollStateChanged(int arg0) { } }); } @Override public void onTabReselected(Tab tab, FragmentTransaction ft) { } @Override public void onTabSelected(Tab tab, FragmentTransaction ft) { // on tab selected // show respected fragment view viewPager.setCurrentItem(tab.getPosition()); } @Override public void onTabUnselected(Tab tab, FragmentTransaction ft) { } }
Hi there! I am Founder at androidhive and programming enthusiast. My skills includes Android, iOS, PHP, Ruby on Rails and lot more. If you have any idea that you would want me to develop? Let’s talk: ravi@androidhive.info
You have got the best Android tutorial blog in the whole internet. Android Dev is an exception. Thank you and stay informative, man!
Thanks Khalid, I’ll do.
Nice article!
Ah, May you let me know the name of the software that you use to make the figure image at Layout Overview session?
Adobe Illustrator. http://www.adobe.com/in/products/illustrator.html
even see this link http://javatyro.blogspot.in/2013/09/android-swipeview-example.html
Not working at api version 8 check it
its not supposed to, the action bar was introduced after API11 so I suggest you use Sherlok Action bar library if you want to support versions down to 8.
No.. There must be some way out. IM working on same. Will let U know.
Try using FragmentTabHost with Fragment ..
It’s working great.
First of all thanks for your quick reply on my request.
Now if I need to start a new activity say new fragment from with in same fragment on click of a button. how could we do that.
Thanks.
Just start the activity from fragment class. Place a button in fragment_games.xml and write activity launch code in GamesFragment.java and test
Hi Ravi,
I was not specified with my question.. 🙁
Exactly what I need to know is undermentioned ::
Say I have 3 tabs –> Tab1 / Tab2 / Tab3.
Considering Tab1 –> Here I have Fragment class Say GamesFragment.java. This Fragment class have a button. Now when I click on button I need to replace fragment_games.xml with fragment_cricket.xml with it’s corresponding class CricketFragment.java.
Note* :-> This fragment_cricket.xml still exists in Tab1 … i.e. I need all tabs through out application while replacing fragments.
I will be thankful to you if you could manage your time for this. Really stuck on this.
Hi Vivek, I have the same problem than you did you find a solution?? Thanks for your help.
Hi Tom,
If your requirement is not using an action bar tab then you can do same using Fragment and FragmentTabHost. U can do every thing with that.
for ex: U can put tab at bottom / Make your tab work with back compatibility.
I did my stuff using same and it’s working great.
Let me know if you need my help on that. I can let you get a quick start with that.
Thank you for your response.
It was not exactly my question. ^^
I want to replace on the same fragment an other fragment. I want to replace login fragment by register fragment when a button was clicked. My fragments are created dynamically and I use the replace function. The problem is when I try to do this, the login fragment is still visible. I have the feeling that the first fragment are not remove or update. I try a lot of thing that I have read on stackoverflow..but nothing work.
If U have an idea it will be help me. Thank you anyway!
Hi Tom,
I posted comment for you over here .. But IM not finding that.
Let me know if you found that .. as IM not able to see that .
Hi Vivek, IM not able to see your comment too. Can we exchange our emails? I can’t see your mail on your profil.. Thank U for your help. Bye
Hi Tom,
Check out same on StackOverFlow.
http://stackoverflow.com/questions/18120510/dynamically-changing-the-fragments-inside-a-fragment-tab-host/19859871#19859871
Hope it helps.
Enjoy!
http://stackoverflow.com/questions/18120510/dynamically-changing-the-fragments-inside-a-fragment-tab-host/19859871#19859871
Hope it helps!
Enjoy.
http://stackoverflow.com/questions/18120510/dynamically-changing-the-fragments-inside-a-fragment-tab-host/19859871#19859871
Check this out. Posted on StackOverFlow.
Hope it helps !
Enjoy.
Hi Tom,
Check out my response on Stack.
http://stackoverflow.com/questions/18120510/dynamically-changing-the-fragments-inside-a-fragment-tab-host
viewPager.setCurrentItem(0); 0 is first tab and so , you can set it your tab number 🙂
This is a best blog for Android Developer. Thanks you so much.
great tutorial !
But I have a question
how to change TextView in fragment from Activity ?
you can using obsever patern for to do this.
Can we add the view above tabs?
ActionBar.TabListener is not implementing to my MainActivity class
What do you mean by not implementing.
Just try clean and built your project. There’s nothing wrong in the given code. Else it is not compatible with lower api’s.
Hope it helps.
Hi,
Thank You For Your Tutorial.
But I don’t need action bar in above project, what i have to do for that?
I don’t know exactly whether we can do that or not
http://stackoverflow.com/questions/14989372/android-hide-actionbar-keep-tabs
Try this on onCreate method . I have tested this.. it’s working.
Let me know if any other concerns.
getActionBar().setDisplayShowHomeEnabled(false);
getActionBar().setDisplayShowTitleEnabled(false);
so good
nice post!! nice webSite!!
Hi, can i use ListView with TopRatedFragment.java for example? findViewById is not working here.
Hey Did u got any solution for list view
?
use getView()
ListView lv =(ListView)getView().findViewById(R.id.list);
Sorry for a very basic question. But how to add ViewPager from eclipse palette? I am not finding one.
i’m doing exactly same with this tutorial, but i have a problems with TabsPagerAdapter.java
an error occur at the fragment, and it said “Type mismatch: cannot convert from SensorFragment to Fragment”
what’s i’m missing?
It worked for me! Thanks so much.
Hi nice tutorial congrats…
but I have a doubt how can I put some data in the layout i.e. “Top Rated” ?
Thank you so much! Awesome Example/Tutorial.
Hello, excellent tutorial, it took me two days looking for a tutorial to serve me and this was the best.
but I have a question, as I can do so that when you turn the screen redraw is closed at this time the app to rotate the screen.
sorry for the English, is google translator
Excellent article that unravels Viewpager and tablayout. Such articles will surely inspire millions of mobile apps and games developers who have been providing with newer versions to the leading mobile ad network companies like revmob, chartboost, adcolony, appnext and others
Hi Ravi, another awesome tutorial, really helpful
May i know how to show text like this : Top Rated instead of TOP RATED
How to add custom List View in this?? it is giving error
can i add a button in one of the tab and link to another page?
ya
u can add button
This is great! Thanks a lot! You saved my day
Followed to the letter this tutorial but cannot get past step #2. I’m getting “ActionBar cannot be resolved to a type”.
I tried modifying the manifest file to select a minimum of API 11 (per the suggestion) and rebuild my project.
I’m still getting that error. Otherwise, looking forward to this tutorial as I needed such an enhancement for my project.
Type this in within import statements: import android.app.ActionBar;
import android.app.ActionBar.Tab;
Thank you, it was a mess before. Now it is much clearer.
how to change title ,i want to change title to my custom title …
I’m getting “The method onTabSelected(ActionBar.Tab, FragmentTransaction) of type MainActivity must override or implement a supertype method” . please help me!
And Also “The type MainActivity must implement the inherited abstract method ActionBar.TabListener.onTabSelected(ActionBar.Tab, FragmentTransaction)”
Hi Ravi,
Thanks 100 % for this tutorial.
But here is my big challage:….. even “Nirmal” asked about it!
How to put Expandable list views within the fragments:
that is:
ExpanbableListView in Top-rated
ExpanbableListView in Games
ExpanbableListView in Movies.
I tried many ways!! but my TabAdapterClass always gets this error:
– Type mismatch: cannot convert from Top-rated to Fragment.
– Type mismatch: cannot convert from Games to Fragment.
– Type mismatch: cannot convert from Movies to Fragment
Please Ravi or anyone….. interested in helping me overcome this challenge. Please in box me kwevany@gmail.com
Hi Ravi,
Firsdt of all a very nice tutorial
Hi Ravi,
First of all a very nice tutorial. I have been following Androidhive since very long. I have created tabs as per http://www.androidhive.info/2011/08/android-tab-layout-tutorial/ Since TabActivity is deprecated from API Level 13, I want to know how can I change my code to integrate FragmentManager to achieve the same results.
Thanks for your help…
I was trying to get it from Android docs… not so clear, not so easy
Thanks a lot.
Thank you for this clearly structured description, fantastic
Hello,
I want to change tab color and tab text color?
How i want to implement that?
Try this … Hope it helps 🙂
Here tabHost is TabHost… In case of fragment this would be FragmentTabHost.
Also ..
Not sure for ActionBarTabs.
——————– code ——————————
for(int i=0;i<tabHost.getTabWidget().getChildCount();i++)
{
TextView tv = (TextView) tabHost.getTabWidget().getChildAt(i).findViewById(android.R.id.title);
tv.setTextColor(Color.WHITE);
tabHost.getTabWidget().getChildAt(i).setBackgroundColor(Color.parseColor("#765433"));
}
tabHost.getTabWidget().setCurrentTab(0);
tabHost.getTabWidget().getChildAt(0).setBackgroundColor(Color.parseColor("#8c6b48"));
}
Thank you for this great tutorial. Also works flawless with ActionBarSherlock !!!
Awesome tutorial, thanks.
Great tutorial, was really helpful. How can I include a webview in the fragments instead of the textview?
Same as U do using activity. There’s nothing change in fragment than activity else fragment provide an easy way to replace view’s.
I’ve added lists and I’m struggling with adding action listeners to the list how can i go about this?
Specify your question what exactly U did and what exactly U require.
Hi You,
I want to ask, for example, is rated one tab button in, press the button to move through the tab Game Sharing, which I could not get through it, and then sharing transfer functions like, thank you very much
i have page with listView…but not working……Any Proper Suggestions
Me tooooooooo!
I’ve tried did this with ListView in each ViewPager (Tab).
But what I got was the list items didn’t respond to my touching, like out of focus.
Please help
Thanks for this tutorial. But I struggle at step 6. Everything is set as you described it, no Errors from Eclipse. But when I run the app it crashes and my logcat says: http://pastebin.com/WYTTQzAQ
NullPointer doesn’t really help a lot… do you know what could be wrong? As I sad, my MainActivity and the corresponding xml file are just as yours.
nice Ravi . please teaching android server database programming. and make a example . like a Market app that working with server database.
nice one, i’m having trouble getting button clicks to pass from the fragment to the activity to play a sound on click. Any tips? i’ve tried the following with a “buttonPressed” tag in my xml for my fragment. but so far no good. thanks
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_traditional, container, false);
//******************getting button clicks*******************
Button a = (Button) rootView.findViewById(R.id.button1);
a.setOnClickListener((OnClickListener) this);
//**********************************************************
return rootView;
}
//******************getting info from xml tagline “onClick= buttonPressed”
public static void buttonPressed(View v) {
switch(v.getId()){
case R.id.button1:
System.out.println(“button1”);
break;
}
}
hi!
i’m using this and it’s very good.
But i want to make an exit if the back button pressed in 2sec.
How can i manage that and which class should i put it in?
before using fragments i’m did it this way:
private static final long DOUBLE_PRESS_INTERVAL = 2000000000;
private long lastPressTime;
public void onBackPressed() {
// Toast.makeText(getActivity(),
// Resources.getSystem().getString(R.string.kilepes_dupla),
// Toast.LENGTH_SHORT).show();
long pressTime = System.nanoTime();
if (pressTime – lastPressTime <= DOUBLE_PRESS_INTERVAL) {
// this is a double click event
System.exit(0);
}
lastPressTime = pressTime;
}
Hi Sir, i try to download the code and implement it in my project, however there is a lot of errors. – like ActionBar cannot be resolved to a type. how do i remove those errors ?
You have to keep the android version above 3.0
hi, my android version is 4.3. do i need to create additional files on top of those given ?
Did you try setting the minimum sdk version to 11 in the manifest file?
weirdly enough it gives this error and doesn’t suggest importing actionbar but you can.
use import android.app.ActionBar;
http://www.androidhive.info/wp-content/uploads/2013/10/Tabs-Illustration.jpg
Hey admin.
Which tool did you use to create this image.
Adobe Photoshop and Illustrator.
How can I change the Fragments used in each Tab? For Example: Tab 1 has its default Fragment A. Fragment A has a button which calls Fragment B. If it is pressed, Fragment A disappears and Fragment B appears. All in the same tab.
How can this be done?
For each tab You ll b having a class file no??
Create an interface and in the MainActivity along with the
“implements Actionbar”.TabListener” append this too ” ClassName.Interface” followed by a comma ( , )
then Pass a reference through that interface and in that interfaces method with the help of fragment manager replace the Fragments
Hi, I didn’t really understand the second part? Can you please explain further, or with an example? Thank you
how can you change fragment with button call ?
Hello! I think that the article which you have written is fantastic!
I would like to consult a doubt. I am developing an application and I have a little problem with it. How could I combine the navigation of the tabs with the navigation drawer?
I have an ActivityMain that it extend to ActionBarActivity with navigation drawable. I would like to do that if you choose a determinate Fragment, it will do a different Tabs with Swipeable Views.
Thank you very much. I wish someone has a break for answer me. Sorry, I don’t speak English very well.
Hi Ugarte,
As per android docs, the suggested way is not using Tabs when your app has navigation drawer. You should use only one of them.
Thank you for your answer. I don’t found the way to do it but, It has to be possible to do it because many applications use it. For example, Google Play, Play Games, Play Books…
I divide the information with Navegation Drawer and I divide that information in categories with the Tabs.
Thank you
Hi Ravi,
Your web is great, keep it up !
I managed to add a webview to a fragment and to keep its state after switching fragments ( using myWebView.saveState(webViewBundle); in onpause method and restoring it )
But it’s working slow. It took like 3 seconds to switch back the fragment with the webview (Running in Atrix 2)…
I’ve been searching but i haven’t found anything about it except this http://stackoverflow.com/questions/19925776/android-webview-restore-state-pretty-slow , same problem with no answers.
Is this normal ? Do you have any suggestion?
Thanks in advance
Gabriel
Hi. This is a great help in my project but when i run my project it stopped. Can you help me with this? Seriously im a beginner in android.