Creating Navigation tabs using TabHost and Fragments in Android

July 31, 2012
By

In this article, we will develop an  Android application containing navigation tabs. There are many ways by which we can add navigation tabs to an application.



Beginning with Android 3.0, the standard way to create navigation tab is using action bar. Please read the article titled ” Adding Navigation Tabs containing listview to Action Bar in Android” to see how to create navigation tabs in Android 3.0 and above.

For Android 2.x and above, we can use Action bar Sherlock library to create navigation library. Please read the article titled ” Adding Navigation tabs containing listview to Action Bar in Pre Honeycomb versions using Sherlock library” to see how to create navigation tabs using Sherlock library.



In this application, we are creating navigation tabs using TabHost and Fragments. Since fragments are available only with Android 3.0 and above, we will make use Android’s support library to work this application in Android 1.6 and above.

This application is developed in Eclipse 3.7.2 with ADT plugin (20.0.2) and Android SDK ( R20.0.1 ) .


1. Create a new Android application project namely “NavigationTabDemo”

New Android Application Project

Figure 1 : New Android Application Project


2. Design Application Launcher

Design Application Launcher

Figure 2 : Design Application Launcher


3. Create a blank activity

Create a blank activity

Figure 3 : Create a blank activity


4 .Enter Main Activity Details

Enter MainActivity Details

Figure 4 : Enter MainActivity Details


5. Adding Android’s Support library

With ADT plugin version 20.0.2, Android’s support library is added to the project automatically. If not added automatically, then you can add it by Right click “NavigationTabDemo” ( Package Explorer ) and select Android Tools -> Add Support Library


6. Download the given below file and extract to drawable-ldpi


7. Download the given below file and extract to drawable-mdpi


8. Download the given below file and extract to drawable-hdpi


9. Create a new folder drawable in res and create a new file namely android.xml with the given below code

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:state_selected="true"
        android:state_pressed="false"
        android:drawable="@drawable/android_selected" />
    <item
        android:drawable="@drawable/android_unselected" />
</selector>

10. Create new file namely apple.xml in res/drawable directory created in the above step and add the given below code

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:state_selected="true"
        android:state_pressed="false"
        android:drawable="@drawable/apple_selected" />

    <item
        android:drawable="@drawable/apple_unselected" />
</selector>


11. Update the layout file res/layout/activity_main.xml

<TabHost
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TabWidget
            android:id="@android:id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="0"/>

        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_weight="0"/>

        <FrameLayout
            android:id="@+id/realtabcontent"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"/>

    </LinearLayout>
</TabHost>

12. Create new class file src/in/wptrafficanalyzer/navigationtabdemo/AndroidFragment.java

package in.wptrafficanalyzer.navigationtabdemo;

import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class AndroidFragment extends ListFragment{

    /** An array of items to display in ArrayList */
    String android_versions[] = new String[]{
        "Jelly Bean",
        "IceCream Sandwich",
        "HoneyComb",
        "Ginger Bread",
        "Froyo"
    };

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        /** Creating array adapter to set data in listview */
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity().getBaseContext(), android.R.layout.simple_list_item_multiple_choice, android_versions);

        /** Setting the array adapter to the listview */
        setListAdapter(adapter);

        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public void onStart() {
        super.onStart();

        /** Setting the multiselect choice mode for the listview */
        getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
    }
}


13. Create new class file src/in/wptrafficanalyzer/navigationtabdemo/AppleFragment.java

package in.wptrafficanalyzer.navigationtabdemo;

import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class AppleFragment extends ListFragment{

    /** An array of items to display in ArrayList */
    String apple_versions[] = new String[]{
        "Mountain Lion",
        "Lion",
        "Snow Leopard",
        "Leopard",
        "Tiger",
        "Panther",
        "Jaguar",
        "Puma"
    };

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        /** Creating array adapter to set data in listview */
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity().getBaseContext(), android.R.layout.simple_list_item_multiple_choice, apple_versions);

        /** Setting the array adapter to the listview */
        setListAdapter(adapter);

        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public void onStart() {
        super.onStart();

        /** Setting the multiselect choice mode for the listview */
        getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
    }
}


14. Create new class file src/in/wptrafficanalyzer/navigationtabdemo/DummyTabContent.java

package in.wptrafficanalyzer.navigationtabdemo;

import android.content.Context;
import android.view.View;
import android.widget.TabHost.TabContentFactory;

public class DummyTabContent implements TabContentFactory{
    private Context mContext;

    public DummyTabContent(Context context){
        mContext = context;
    }

    @Override
    public View createTabContent(String tag) {
        View v = new View(mContext);
        return v;
    }
}


15. Update the file src/in/wptrafficanalyzer/navigationtabdemo/MainActivity.java

package in.wptrafficanalyzer.navigationtabdemo;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.widget.TabHost;

public class MainActivity extends FragmentActivity {
    TabHost tHost;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tHost = (TabHost) findViewById(android.R.id.tabhost);
        tHost.setup();

        /** Defining Tab Change Listener event. This is invoked when tab is changed */
        TabHost.OnTabChangeListener tabChangeListener = new TabHost.OnTabChangeListener() {

            @Override
            public void onTabChanged(String tabId) {
                android.support.v4.app.FragmentManager fm =   getSupportFragmentManager();
                AndroidFragment androidFragment = (AndroidFragment) fm.findFragmentByTag("android");
                AppleFragment appleFragment = (AppleFragment) fm.findFragmentByTag("apple");
                android.support.v4.app.FragmentTransaction ft = fm.beginTransaction();

                /** Detaches the androidfragment if exists */
                if(androidFragment!=null)
                    ft.detach(androidFragment);

                /** Detaches the applefragment if exists */
                if(appleFragment!=null)
                    ft.detach(appleFragment);

                /** If current tab is android */
                if(tabId.equalsIgnoreCase("android")){

                    if(androidFragment==null){
                        /** Create AndroidFragment and adding to fragmenttransaction */
                        ft.add(R.id.realtabcontent,new AndroidFragment(), "android");
                    }else{
                        /** Bring to the front, if already exists in the fragmenttransaction */
                        ft.attach(androidFragment);
                    }

                }else{    /** If current tab is apple */
                    if(appleFragment==null){
                        /** Create AppleFragment and adding to fragmenttransaction */
                        ft.add(R.id.realtabcontent,new AppleFragment(), "apple");
                     }else{
                        /** Bring to the front, if already exists in the fragmenttransaction */
                        ft.attach(appleFragment);
                    }
                }
                ft.commit();
            }
        };

        /** Setting tabchangelistener for the tab */
        tHost.setOnTabChangedListener(tabChangeListener);

        /** Defining tab builder for Andriod tab */
        TabHost.TabSpec tSpecAndroid = tHost.newTabSpec("android");
        tSpecAndroid.setIndicator("Android",getResources().getDrawable(R.drawable.android));
        tSpecAndroid.setContent(new DummyTabContent(getBaseContext()));
        tHost.addTab(tSpecAndroid);

        /** Defining tab builder for Apple tab */
        TabHost.TabSpec tSpecApple = tHost.newTabSpec("apple");
        tSpecApple.setIndicator("Apple",getResources().getDrawable(R.drawable.apple));
        tSpecApple.setContent(new DummyTabContent(getBaseContext()));
        tHost.addTab(tSpecApple);

    }
}


16. Update the file AndroidManifest.xml


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="in.wptrafficanalyzer.navigationtabdemo"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.Black" >

        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>


17. Screenshot of the application in execution

Screenshot of the application in Execution

Figure 5 : Screenshot of the application in Execution


18. Download


19. Reference

http://developer.android.com/guide/index.html


How to hire me?

I am George Mathew, working as software architect and Android app developer at wptrafficanalyzer.in

You can hire me on hourly basis or on project basis for Android applications development.

For hiring me, please mail your requirements to info@wptrafficanalyzer.in.

My other blogs
store4js.blogspot.com


Android Knowledge Quiz

Ready to test your knowledge in Android? Take this quiz :



Tags: , , , , ,

31 Responses to Creating Navigation tabs using TabHost and Fragments in Android

  1. Bilal Sammour on August 23, 2012 at 2:58 pm

    i’ve run NavigationTabDemo on my galaxy nexus (android 4.1), the top tabs (android, apple) dose net appear

    • jose vicente on August 23, 2012 at 10:17 pm

      I’ve also installed it and the tabs don’t appear. I can only view the list.

      • george on August 24, 2012 at 6:00 am

        Thank you for reporting this bug.
        This bug can be fixed by removing the line android:orientation=”vertical” from the layout file activity_main.xml

  2. jose vicente on August 23, 2012 at 10:22 pm

    The problem in these two functions:
    public View createTabContent(String tag)
    public void onTabChanged(String tabId)
    show 2 errors (1 error from each one), and eclipse tells you to remove the @Override if you want to go on.
    When it is removed, debug can be started, but then the tabs don’t appear, only the list appears (and the list and checkboxes work fine).
    Could you please help me?

  3. jose vicente on August 23, 2012 at 10:25 pm

    I forgot the manifest:

  4. jose vicente on August 23, 2012 at 11:42 pm

    Well. The manifest comes with the project you published. It is the same.

  5. frank on September 28, 2012 at 9:23 pm

    If I didnt want to use icons in the tabs, and just use plain text. Like I just want the tab to say “Media List”. What code would be changed?

  6. saurabh jain on October 1, 2012 at 5:11 pm

    Remove the getResources().getDrawable in setIndicator

  7. Sujit on October 5, 2012 at 5:12 pm

    I cannot see image on tabs for api level 15(android 4.0), but could see it for lower apis. How can i fix it?

  8. AL on October 12, 2012 at 8:27 pm

    Thanks!

    How can I change Tab style through XML file?
    I don’t know hot to apply a Inflater for the custom layout of the single tabs.

  9. ahong222 on November 11, 2012 at 1:04 pm

    if I haven’t use ListFragment, how to keep user’s check,because onCreateView always be invoked

  10. Vipul Purohti on January 24, 2013 at 5:32 pm

    How to open new activity or fragment within the tab ?
    and how to manage stack view ?

  11. Boris on January 30, 2013 at 4:34 pm

    Thanks a lot for this example, especially for

    tSpecAndroid.setContent(new DummyTabContent(getBaseContext()));

    Because if using tabSpec.setContent(tabContentId); nothing to appears when tab showed at first time. You save me!))

  12. Nilesh Jarad on February 21, 2013 at 6:44 pm

    Can any one tell me What is Exact use of DummyTabContent class

    Thnks in andvance.

    • george on February 22, 2013 at 5:00 am

      DummyTabContent is an instance of TabFactoryContent which is used to create view content for the tabs.

      In this example, the view content is empty initially and its contents are being added at run time by fragments.

  13. Márcia on February 21, 2013 at 11:57 pm

    I, can you tell me how to implement onItemClickListener in ListFragment? Thanks!

  14. jordi on April 11, 2013 at 3:52 pm

    Hi,
    Thanks for this example. But, I need customize a ListView in both ListFragments. How can i do? Can I helkp me?

    Thank you George!

  15. Cecilia on June 14, 2013 at 11:28 pm

    Hi, thank you so much for publishing this tutorial.
    I am following this tutorial but I am getting a NullPointerException at this line: tHost = (TabHost) findViewById(android.R.id.tabhost);
    How can I solve this problem?

    • Cecilia on June 15, 2013 at 12:45 am

      I have just solved the problem. The problem was solved just changing the parameter of setContentView by my custom layout id instead of activity_main.

  16. Jinal Jogiyani on June 27, 2013 at 3:27 pm

    I downloaded full code….but when I m Import and run this app. the error occured :

    06-27 15:17:34.300: W/dalvikvm(20853): Unable to resolve superclass of Lin/wptrafficanalyzer/navigationtabdemo/MainActivity; (6)
    06-27 15:17:34.305: E/AndroidRuntime(20853): FATAL EXCEPTION: main
    06-27 15:17:34.305: E/AndroidRuntime(20853): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{in.wptrafficanalyzer.navigationtabdemo/in.wptrafficanalyzer.navigationtabdemo.MainActivity}: java.lang.ClassNotFoundException: in.wptrafficanalyzer.navigationtabdemo.MainActivity in loader dalvik.system.PathClassLoader[/data/app/in.wptrafficanalyzer.navigationtabdemo-1.apk]
    06-27 15:17:34.305: E/AndroidRuntime(20853): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1573)
    06-27 15:17:34.305: E/AndroidRuntime(20853): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
    06-27 15:17:34.305: E/AndroidRuntime(20853): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
    06-27 15:17:34.305: E/AndroidRuntime(20853): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
    06-27 15:17:34.305: E/AndroidRuntime(20853): at android.os.Handler.dispatchMessage(Handler.java:99)
    06-27 15:17:34.305: E/AndroidRuntime(20853): at android.os.Looper.loop(Looper.java:123)
    06-27 15:17:34.305: E/AndroidRuntime(20853): at android.app.ActivityThread.main(ActivityThread.java:3691)
    06-27 15:17:34.305: E/AndroidRuntime(20853): at java.lang.reflect.Method.invokeNative(Native Method)
    06-27 15:17:34.305: E/AndroidRuntime(20853): at java.lang.reflect.Method.invoke(Method.java:507)
    06-27 15:17:34.305: E/AndroidRuntime(20853): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847)
    06-27 15:17:34.305: E/AndroidRuntime(20853): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
    06-27 15:17:34.305: E/AndroidRuntime(20853): at dalvik.system.NativeStart.main(Native Method)
    06-27 15:17:34.305: E/AndroidRuntime(20853): Caused by: java.lang.ClassNotFoundException: in.wptrafficanalyzer.navigationtabdemo.MainActivity in loader dalvik.system.PathClassLoader[/data/app/in.wptrafficanalyzer.navigationtabdemo-1.apk]
    06-27 15:17:34.305: E/AndroidRuntime(20853): at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:240)
    06-27 15:17:34.305: E/AndroidRuntime(20853): at java.lang.ClassLoader.loadClass(ClassLoader.java:551)
    06-27 15:17:34.305: E/AndroidRuntime(20853): at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
    06-27 15:17:34.305: E/AndroidRuntime(20853): at android.app.Instrumentation.newActivity(Instrumentation.java:1021)
    06-27 15:17:34.305: E/AndroidRuntime(20853): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1565)
    06-27 15:17:34.305: E/AndroidRuntime(20853): … 11 more

    • george on June 27, 2013 at 3:41 pm

      Hi,
      Please do the following :

      * Open properties window by right clicking the project from project explorer

      * Select Java Build Path -> Order and Export tab

      * Ensure “Android Private Libraries” is checked

      * If unchecked, “check” it and click ok

      * Clean and Build the project and run the application

  17. Venkatraman on July 20, 2013 at 1:35 pm

    Hi,
    I reffered this sample for my testing purpose and I am getting below exception on switching b/w tabs after adding menu options. what could be wrong in that…
    07-20 13:31:20.765: E/AndroidRuntime(11185): FATAL EXCEPTION: main
    07-20 13:31:20.765: E/AndroidRuntime(11185): java.lang.NullPointerException
    07-20 13:31:20.765: E/AndroidRuntime(11185): at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:611)

    Kindly advise

  18. Malik Qirtas on August 26, 2013 at 5:55 pm

    Hi How i can change the background of tabwidget plzz help mee

  19. chandu on September 2, 2013 at 1:23 pm

    hi

    i want to arrange tabs vertically on the left side look like this

    http://i.stack.imgur.com/FtyMv.png

    please reply me

  20. Jesus Rodriguez on November 11, 2013 at 11:59 am

    As I can solve the problem of the application that turning the device remains in the selected tab.

    Thanks for your tutorials.

  21. Nirav Joshi on December 8, 2013 at 5:30 pm

    Hi

    Thanks a lot for such a nice example.

    But i have a question on it.

    If i will have a dynamic content of a apple_version String array then how will i be able to notify Fragment ?

  22. Kaiser on December 26, 2013 at 10:16 pm

    Hello, George Mathew!

    I have a question and I hope you can actually help since I use your example.
    I use your tabhost with fragment on my application the difference is that instead of ListFragment I’m using Fragment. My issue it’s simple, evertime I change tab and when I get back, my values that are in my EditTextview I loose my data. So do you have any idea in how instance those fragments?

    Thanks

  23. Yehuda on February 1, 2014 at 1:59 am

    Hi, Thank you very much for this tutorial. It is very helpful. I have one question for now. How would I go about adding an edit Text and textView to one of these fragments? I am used to creating the fragments as an actual xml file and not from within a java class. Thanks in advance for the help.

  24. ayoub on March 8, 2014 at 5:06 am

    when i put EditText in the fragment !! don t work

  25. Kumar chandravart on April 28, 2014 at 2:37 pm

    Hello Mathew , thanks for the code, but I need Edit Text field instead of listview, which is not able to take any input,wen i click textfield inside one of tab, it doesn’t respond , not even any error. What could be reason. Please help me. thanks.

Leave a Reply

Your email address will not be published. Required fields are marked *

Be friend at g+

Subscribe for Lastest Updates

FBFPowered by ®Google Feedburner