Tab Layout in Android with ActionBar and Fragment

In a previous post I wrote an example of Layout Tab using a TabActivity class that it is deprecated since version 3.0 Honeycomb of Android.
In this post I develop the same interface using ActionBar and Fragment, and I tried wherever possible to limit the changes to the files *.xml.

  1. create an Android project called TabActionBar, a package eu.lucazanini and an activity TabActionBarActivity.java
  2. edit the file AndroidManifest.xml, it should be the default one
  3. edit the file /res/values/strings.xml, to manage the labels
  4. edit the file res/layout/main.xml, it should be the default one (this file is not used, so you can skip this step, see the comments below)
  5. create the files res/layout/tab1.xml and res/layout/tab2.xml, representing the contents of 2 tabs

  6. edit the class TabActionBarActivity.java, note that the labels of the tabs will be capitalized and that eventually you can put an icon or a view with the methods setIcon or setCustomView
  7. create the classes Tab1Fragment.java and Tab2Fragment.java

  8. launch the app

108 Comments

 Add your comment
  1. Dear Team,
    I made same tab layout pages with action bar..Now i want to choose images or files or capture image via camera but startactivity lost…not call.

  2. Error !!!!!
    Unable to start activity ComponentInfo{com.Resto.menuresto/com.Resto.menuresto.AcceuilActivity}: java.lang.NullPointerException: Attempt to invoke virtual method ‘void android.app.ActionBar.setNavigationMode(int)’ on a null object reference
    help me ?

  3. Hi Luca,
    tutorial looks OK.
    Although 2 questions:
    1. How to make tabs not occupying full screen width? Like just one/two tabs on the left/right side.
    2. How to adjust tab width according to the length of the label?

  4. Hi Luca,

    thank you so much for this fine tutorial. I had sooo many problems to implement it but your tutorial show me the right way.

  5. altra domanda se posso,
    come potrei aggiungere lo scrolling orizzontale fra le tab? quindi senza dover premere il tasto dell’action bar, ma cambiando le tab con un semplice swipe?

    grazie!

  6. ciao Luca,
    grazie per l’ottimo tutorial!
    se io ho un TextView chiamato tv1 nell’xml di un tab, per esempio tab1, se dal file TabActionBarActivity volessi modificare il contenuto di quel text view (perchè reperisco delle informazioni da un database)
    se provo a fare
    tv = (TextView) findViewById(R.id.tv1);
    tv.setText(….)

    ottengo nullPointerException

  7. I put a button in Tab1Fragment and on clicking it I want to replace Tab1Fragment with Tab3Fragment. How can I do this?

  8. Hi,
    Thank you for yur tutorial.
    I woould like to use a button to do some actions in your example but it doesn’t work when i click on it.
    Do you have an example with button inside tab ?
    tank you for your help.

    • If you add a button to the content below the tabs you can follow this.
      If you want to add the buttons in place of the labels of tabs I am not sure, you can see this and try to add the buttons in the xml layout files.

  9. How to change the layout of the actionbar tabs itself upon changing the state of the tabs, means the layout of the tab should change if it is selected from unselected state. I tried setCustomView() from within my TabListener methods, but that does not seem to work.

  10. how to get the tabs to the middle of the actionbar ??

  11. […] the post Tab Layout in Android with ActionBar and Fragment the fragments can’t be replaced later, in this post I write the changes in order to replace […]

  12. It worked like a charm. Thanks Luca for your excellent tutorial!

  13. Ciao Luca,
    volevo chiederti una cosa:
    ho seguito l’esempio “Adding Navigation Tabs” alla pagina: http://developer.android.com/guide/topics/ui/actionbar.html
    Il tutto funziona perfettamente.
    IL problema sta nel cambiare il contenuto (quindi fragment) sotto un tab.
    Ad esempio ho messo nel fragment caricato sotto il tab_1 un bottone.
    vorrei che quando si preme il bottone venga caricato un altro fragment sempre nello stesso tab.
    In rete si trovano tutti esempi che mostrano il caricamente dei tab inizali con i ripsettivi content, ma non riesco a cambiare po il contenuto…
    grazie mille 🙂

    Armando

  14. If we run this code in 10′ tab, the tabs don’t fill full actionbar…

    I want that tabs should fill whole actionbar.

  15. Ciao,
    Grazie per il tutorial,
    Ho seguito tutti i passi ma il menu lo mette sulla stessa riga dove cè il logo e il nome della app.

    • Se il titolo e il logo sono assenti è come se tu avessi il codice:

      Se invece sono presenti, è la situazione in cui la larghezza del dispositivo è sufficientemente ampia per inserire titolo, logo e tabs in una sola riga, spesso in modalità landscape.

  16. Hi Luca,

    great tutorial.
    All fine, but when I use the app and I select another tab the text overlaps the first one.
    I don’ understand why. Could you give any suggestion?

    Thanks.

  17. Hi,

    I am using the same example as above in my app too. But I am implementing it a little different way.

    In one of the tabs(Search), when user clicks a button, I replace the current fragment with another fragment using
    FragmentTransaction.replace()

    When user clicks button on the new fragment, a new fragment replaces the existing fragment.

    Due to this when I click on another tab and click on the Search Tab, the latest fragment is shown but when I click on back button, I get a Blank page.

    The reason for this is ft.attach() recreates the view according to the documentation.

    Is there a way to preserve the view hierarchy when switching to another tab?

    • FragmentTransaction has the show and hide methods too, so if the fragment is already attached you can try to use them.
      You can catch the back button with:

      or overriding onBackPressed method.

      • I can do that. But I am not sure how to do that.
        Let me explain with example.
        Tab 1 -> Fragment a -> fragment b -> Fragment c
        Tab 2-> Fragment d

        I click on Tab 1, go from a to b to c. When I stay on Tab 1, and I am in ‘a’, clicking back goes to b, clicking back in b goes to ‘a’

        But when I am in Fragent ‘c’. and click on Tab 2 and come back to Tab 1 and click back, I get blank.

        Can you give example on what I should put in those methods? And is onBackPressed() activity method?

        One more question. When constructing the tablistener, we give a fragment as constructor. Is it possible to change the fragment associated with the tablistener later?

  18. action bar example coding is very nice
    very very thanks

  19. you haven’t used setContentView(view) in TabActionBarActivity.java then what’s the use of main.xml?
    and can we navigate through these tabs using swap gesture ?

  20. Hey Luca,

    thanks for the tutorial. Your app runs fine for me as well, however I am struggeling with the layout of the tab widgets. So if I run the app it looks different compared to your screenshots.
    1. I do not have the upper blue border above the tab widgets.
    2. My tab widgets do not fill the whole screen horizontally. Tab1 starts not at the left edge of the screen and tab2 does not end at the right edge of the screen.
    The same happens for my app which I build according to adroids tutorial
    ().
    It is like there is a default max width for the tab widgets.

  21. how to create the tab in middle of the screen???

    • You can’t create an action bar in the middle of the screen.
      In order to have tabs in the middle of the screen you must create a custom layout.

  22. You are a hero. Thankyou so much.

  23. Is it possible the actionbar tabs to navigate to activities instead of fragments?

    • You can’t replace fragment with activities in this example.
      You can call an activity from an other activity using the startActivity method and every activity has its own actionbar.

  24. Hi,

    Your tutorial is great. But is it possible to customize my own tabs using fragmentactivity. I’m having difficulties in converting my current TabActvitiy into using FragmentActivity.

    • In my tutorial I use android.app.Fragment, in FragmentActivity you have to use android.support.v4.app.Fragment.
      Then you can’t start from my example if you use FragmentActivity.

  25. on running this code i am getting an error “R cannot be resolved as a variable”
    what should i do?

  26. Thanks for your insight on this topic!!! I have one question: Why is it when I rotate my phone and select another tab the previous tab remains onscreen with the selected tab?

  27. Thanks for the awesome tutorial !!!

    When I run this tutorial in as standalone project it works fine but I have a Main activity and I want to launch tabbed activity on button click from Main activity. If I just click the button to launch this tabbed activity then it crashed.

    Button drinkListBtn = (Button) findViewById(R.id.main_drink_list_btn);
    drinkListBtn.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
    startActivity(new Intent(Main.this, TabbedActivity.class));

    }
    });

    Logcat is some what like this.
    05-02 16:43:42.309: W/dalvikvm(4337): threadid=1: thread exiting with uncaught exception (group=0x409c01f8)
    05-02 16:43:42.339: E/AndroidRuntime(4337): FATAL EXCEPTION: main
    05-02 16:43:42.339: E/AndroidRuntime(4337): java.lang.RuntimeException: Unable to start activity ComponentInfo

    Any help, Thanks

  28. Hi,

    This is very nice tutorial. I had implemented this tutorial. But I am getting java.lang.NullPointerException
    at statement actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS). So will you please
    help me to resolve this.

    Thanks

    • actionBar seems null.
      actionBar is assigned at the row before:
      ActionBar actionBar = getActionBar();

      I dont’t know why but you can check AndroidManifest.xml, especially the minSdkVersion value.

  29. Hello Luca,
    Thanks for this tutorial, it was very helpful. One possibly more advanced question though, sorry if you’ve already covered this somewhere else.
    If you had 2 Fragments under one tab (for example Tab1Fragment1 and Tab1Fragment2) and Tab1Fragment1 was added when the tab was created. If you navigate to Tab1Fragment2, then change orientation, this would reload the Activity and call onCreate which would add Tab1Fragment1 again. How would I stop the ActionBar using the Tab1Fragment1 and use Tab1Fragment2 instead? Would I need to re-add the second Fragment later or how would I attach it again?
    Thanks for any help you can give me, Ben

  30. Hello Luca,

    By clicking on the tabs the methods onCreateView and onActivityCreated are always initiated, it is possible to save the state of the Fragment to the screen not recreated?

    • Replace ft.attach(mFragment); with ft.show(mFragment); and ft.detach(mFragment); with ft.hide(mFragment);
      If you want to save the state of the fragment consider to override the onSaveInstanceState method.

      • Luca,

        The my problem the is following, when using the TabActivity to navigate between tabs Activity, when changing tabs starts the onCreate once every Activity, but always passes by onResume, in the Android version 4 is informed that this deprecated TabActivity , so the only way would be to use the ActionBar navigation and to convert my in Fragment Activity? Or is it possible to navigate between Activity in ActionBar or otherwise in another way in Android 4?
        Regarding the first case,modify Activity for Fragment, always change the tabs the interface and rebuilt in Fragment and passes through the methods onCreateView and onActivityCreated, however needed that behaves coforme navigation between Activity, and only go through onResume.

        • In ActionBar navigation you must use Fragments and not Activities.
          As I say before, if you replace

          ft.attach(mFragment); with ft.show(mFragment);
          ft.detach(mFragment); with ft.hide(mFragment);

          the onCreateView and onActivityCreated methods are not called.

  31. Hi Luca!! It’s a wonderful tutorial thanks for that.i had a question like how to add picture(image) on the each tab instead of “one” “two”.
    Thanks…

  32. Hi!

    I believe this is a good tutorial but I can`t seem to get the positioning right.
    The tab widget is displayed on the rigth side of the app name and all I can see is the tab “One”.
    I can see the tab content “Tab one”.
    I can`t see what you show when you launch the app.
    I launch it through a virtual device.

  33. First off thanks a lot for the good tutorial.

    I’m running into a problem,
    TabListener a = new TabListener(this, getString(R.string.title_new), New_tab.class);

    give me an error: Bound mismatch: The type New_tab is not a valid substitute for the bounded parameter of the type Main.TabListener

    any ideas?

  34. […] The idea for this post came to me after reading the comment of Esthon Wood: “do you have any idea on how to save the state of the WebView? I mean, the webview refreshes everytime I tap on the tab.” in the post Tab Layout in Android with ActionBar and Fragment. […]

  35. […] the post Tab Layout in Android with ActionBar and Fragment I wrote an example about tabs in an action bar where each label open a fragment that you can not […]

  36. Hello

    Excellent tutorial Luca!! I have a question regarding Fragments.

    This is how i create my tabs

    ActionBar actionBar = getActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    Tab tabA = actionBar.newTab();
    tabA.setText(R.string.tab1);
    tabA.setTabListener(this);
    actionBar.addTab(tabA); //same for the other tabs

    Then i implement the ActionBar.TabListener

    @Override
    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
    Fragment fragment = null ;

    if (tab.getPosition() == 0){
    fragment = new TabAFragment();

    }//initialise all Tab Fargments
    if (fragment != null){
    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    //container is a framelayout in the main_activity layout
    transaction.replace(R.id.container, fragment);
    transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
    transaction.commit();
    }
    }
    @Override
    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
    }
    @Override
    public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
    }

    Say TabAFragment has a Button and i want to display the contents of the resulting layout within TabAFragment layout, am i right to do this
    ………. //some declaration missing
    fragment = new TabAButtonFragment();
    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    transaction.replace(R.id.container, fragment);
    transaction.addToBackStack(null);
    transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
    transaction.commit();

    Thanks

  37. Hi Luca,
    First of all, thanxs so much for this tutorial because I’ve been looking for days trying to find something like this and it was just impossible.
    I want to ask you how to personalize the tabs like getting them at the bottom, changing color, etc…

    THANK YOU

  38. Hi Luca, thank you for this great tutorial! This is the only one that I have tried that worked flawlessly. I want to add a WebView to one of the tab layouts (tab2.xml) to display a website but I get a NullPointerException when I try to load the URL. Any suggestions on how to properly add a WebView to a tab layout? Thanks 🙂

    • Add the WebView to a layout, for example tab2.xml
      Replace the onCreateView event with:

      This code requires

      Remember to add the permission

      in your AndroidManifest.xml

      • This is awesome. Thanks Luca! One last thing, do you have any idea on how to save the state of the WebView? I mean, the webview refreshes everytime I tap on the tab. Thanks again =)

  39. Best tutorial out there! Thank you! This is the only thing on the web that works for me! Straightforward and simple! good stuff!

  40. Thanks for the tutorial.. found this after searching for 2 days and it solved the problem for me.

  41. Hi, usefull tutorial !

    Now i manbage to have multiple layouit loaded into tabs =)

    But as a beginner, i wonder how to access the controls in my tab1 and tab2 fragment class.

    How can i set onClickListeners in theses controls ? (eg on textview1)

    Thanks

    • You can replace onCreateView in Tab1Fragment.java

      Otherwise you can implement OnClickListener in the class Tab1Fragment.

  42. Thank you soou much for your tutorial man. I have been searching for tabs with fragments tutorial for two hours and this one did the magic. Keep up the good work 🙂

  43. Thank u lot for this useful tutorial

  44. Thank you a lot for taking the time to write this tutorial! saved me a lot of time.

    God Bless!

  45. Hi,

    I have 2 tabs, one of them contains very long text so I put a TextView inside ScrollView in one of the fragment.
    Now I scroll down in the tab, select other tab and again select the first tab, I always get my scroll positioned on top.
    I want it to be at same position where user leaves it even after changing tabs.
    Am I missing something in this code? or I have to workout something else?

    Regards,
    Bhavin.

  46. i have tried the example. i found that if i use tab1 now, then press home button and turn to setting to set the language to another one, tab1 would be created twice when the activity launched again. If you can help me that would be great.

  47. Hello Luca, I have recreated your tutorial I think faithfully but notwithstanding I have 4 errors that won’t allow launch.

    The errors are essentially the same in the .java class files using getResources the IDE claims the strings.xml file symbol variables cannot be found?

    This is in spite of the fact that the R file contains the IDs for label1, label2, tab1 and tab2.

    Any suggestions as to why these errors?

    Please advise, David.

    • Check the file res/values/strings.xml
      Are you sure you are not getting the resources inside a static class or method?
      The inner class TabListener must not be static.

  48. Hello, the tutorial is just great. Congratulations!
    I have a doubt that maybe you can solve.
    Let’s say that I have my own View for the layout which only shows “this is the TAB x” where x is 1 or 2 depending on which tab are we. How could you do that? Sending an Inten looks the normal option but from where and how?
    If you can help me that would be great.
    Thanks!

    • I am not sure to understand what you mean.
      The 2 fragment classes can have the same layout resource and you can set a textview in it.

  49. Se in Tab1Fragment ho un button come faccio a sostituire il fragment attuale con uno nuovo?
    La sostituzione dovrebbe avvenire a seguito dell’onClick() sul button nel fragment 1 e non su un icon dell’action bar…come ad esempio nelle app Android di Instagram o Twitter.

    • Penso che nell’evento click del button ci dovrebbe essere qualcosa come:
      FragmentManager fm = getFragmentManager();
      FragmentTransaction ft = fm.beginTransaction();
      ft.replace(…);
      ft.commit();

      • E’ quello che sto utilizzando anche io ma ho un dubbio sul replace…Ho creato la mia Action Bar seguendo la documentazione ufficiale di Android ed ho visto che coincide con il suo codice ovvero un’activity iniziale in cui viene creata la Bar con le sue tab (fragment). I fragment, quindi, si sostituiscono sempre sulla stessa Activity perchè non ve ne sono altre.
        Nel caso della mia domanda, dunque, la FragmentTransaction deve sostituire a Tab1Fragment un NuovoFragment sempre nell’activity di partenza e quindi nella replace() ho indicato come secondo parametro il nuovo fragment ma come primo?
        Ho utilizzato in altri progetti i Fragment e le FragmentTransaction ma sempre utilizzando un’activity per ogni Fragment e sostituendoli con gli xml.

        Grazie per la risposta.

        • Il primo parametro è l’id del container in cui sostituire il fragment.
          In questo post l’id del container non è stato definito esplicitamente in un file .xml di layout quindi penso che si dovrebbe usare quello di default: android.R.id.content

          • Si, così ho visto che funziona la sostituzione del fragment ma viene ”sconvolto” il funzionamento della Bar.
            Mi spiego meglio. Nel momento in cui, a seguito dell’OnClick, viene eseguita la FragmentTransaction con il nuovo fragment (lo chiamo N per comodità), se si cambia tab dall’ActionBar, quest’ultimo viene sovrapposto ad N e non sostituito, quindi, continuo a visualizzare il contenuto del fragment N (ad esempio una TextView = Nuovo) con sopra il contenuto del tab selezionato dalla Bar (ad esempio una TextView = Tab x).

          • Sospettavo che si potesse verificare una situazione di questo tipo, probabilmente si deve modificare la classe interna che gestisce le tab (TabListener) e usare il metodo detach di FragmentTransaction per rimuovere il frammento “N” quando non deve essere più visibile.

        • Intende all’interno del metodo onTabSelected() così che ogni volta che si deve usare il metodo attach() per aggiungere un tab dell’ActionBar si rimuova prima il fragment eventualmente presente?

          • Si, direi che quello è il posto più logico ma non l’ho verificato; si dovrebbe rimuovere solo il frammento, se esiste, aggiunto con il bottone, basandosi ad esempio su un tag che identifica quel frammento; ho avuto un problema simile di frammenti che si sovrapponevano e ho risolto con l’uso combinato dei metodi attach e detach.

          • Ho risolto il problema della sovrapposizione modificando in questo modo il metodo:
            public void onTabSelected(Tab tab, FragmentTransaction ft) {
            if (mFragment == null) {
            mFragment = Fragment.instantiate(mActivity, mClass.getName());
            ft.add(android.R.id.content, mFragment, mTag);
            } else {
            if (mFragment.getTag().equals(getFragmentManager().findFragmentById(android.R.id.content).getTag()))
            ft.show(mFragment);
            else {
            ft.detach(getFragmentManager().findFragmentById(android.R.id.content));
            if (mFragment == null)
            { mFragment = Fragment.instantiate(mActivity, mClass.getName());
            ft.add(android.R.id.content, mFragment, mTag);}
            else
            { ft.attach(mFragment);
            }
            }
            }

            Ho testato il codice in varie situazioni e non ha dato problemi ma in questo modo permane ancora l’altro problema ovvero, se, dopo aver visualizzato il Fragment N, seleziono dall’ActionBar il tab 2 e poi ritorno sul tab1, quest’ultimo compare vuoto ovvero non visualizzo più il suo Layout.

          • ft.replace(…) equivale a un remove del precedente frammento + un add del nuovo frammento, e quindi il vecchio frammento non esiste più in quanto sostituito (eliminato).
            O si ricrea il frammento della prima tab quando da tab2 si passa a tab1 oppure si potrebbe verificare cosa succede usando invece del replace() la sequenza hide(frammento da sostituire) + add(frammento nuovo N)

  50. […] the post Tab Layout in Android with ActionBar and Fragment I explain how to implement tabs and in the post Swipe views I explain how to implement the swipe […]

  51. i have tried this example with the ActionBarSherlock and every time i’m using the addTab my programs crashed. does anyone knows how i can fix it?

  52. If you`re on the second tab and you change the tablet orientation you app “restart” and you back to the first tab.
    How fix this?

    • The activity is destroyed and restarted when you rotate the device; in order to avoid this you insert the following line inside the “activity” tag in AndroidManifest.xml
      android:configChanges=”orientation|screenSize”

  53. Thank god for this tutorial.
    I’ve been pulling my hair for two days now.

    Thanks!

  54. […] a previous post I implemented a layout with 2 tabs using an action bar and fragments; the disadvantage of this […]

  55. Excellent! This saved me so much time. Thanks!

  56. Hi

    I realised the text in the tab are in uppercase. Is there a way to change it to lowercase?

Leave a Comment

Your email address will not be published.