If you’re developing an Android app with multiple screens, a great navigation option is tabs. Tabs are particularly useful if your screens are all at a similar hierarchy, for example providing different views of similar information. If you have a very hierarchical structure, tabs may make less logical sense and you may prefer to click deeper into the activity.
Since Android 3.0, the preferred way to do this is using Fragments link. Fragments allows you to break your Activities up into modular pieces, so you can combine and reuse multiple fragments in multiple activities. You can think of a Fragment as a kind of sub activity, managed in part by your main activity. We won’t go into using Fragments in detail here, but we will look at using them to set up a basic tabbed app.
App and layout setup
Create a new project, TabTest, in Eclipse, remembering that it will need to be targeted at Android 3.0 or greater. (I used 4.0.3.) Make sure you use the “with Action Bar” theme.
Our main activity, TabTestActivity, sets up the ActionBar:
public class TabTestActivity extends Activity { ActionBar.Tab tab1, tab2, tab3; Fragment fragmentTab1 = new FragmentTab1(); Fragment fragmentTab2 = new FragmentTab2(); Fragment fragmentTab3 = new FragmentTab3(); protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_tab_test); ActionBar actionBar = getActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); tab1 = actionBar.newTab().setText("1"); tab2 = actionBar.newTab().setText("2"); tab3 = actionBar.newTab().setText("3"); tab1.setTabListener(new MyTabListener(fragmentTab1)); tab2.setTabListener(new MyTabListener(fragmentTab2)); tab3.setTabListener(new MyTabListener(fragmentTab3)); actionBar.addTab(tab1); actionBar.addTab(tab2); actionBar.addTab(tab3); }
ActionBar.Tab is, as you’d expect, a tab in the Action Bar, and we create three of them. We also create three Fragments to hold the content of our three tabs. We’ll create the FragmentTab subclasses in a moment.
We set up the layout as usual (see later section for the XML), grab the ActionBar, and set navigation mode to tabs. The other navigation modes are List, which provides a list menu, and Standard (just has a ‘home’ logo and title text). We then create three new tabs in the ActionBar, assigning them to our ActionBar.Tab class members, and set the title text for each one. You could also usesetIcon(R.drawable.image)
to set an image icon instead.
Finally, we create a new TabListener for each one, and then add all three to the ActionBar. A TabListener provides a callback interface to handle actions applied to tabs, including focusing them, adding them, or removing them. ActionBar.TabListener is an interface, so we’ll need to implement it with the custom MyTabListener class.
Note that as we’re using android.app.Fragment
(not android.app.v4.support.Fragment).
We must also edit AndroidManifest.xml to set the minimum SDK to 13.
Creating the tabs
Having written the main activity, we need to create the tab classes. FragmentTab1.java looks like this:
public class FragmentTab1 extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){ View view = inflater.inflate(R.layout.tab, container, false); TextView textview = (TextView) view.findViewById(R.id.tabtextview); textview.setText(R.string.One); return view; } }
This class must extend Fragment as it is treated as a Fragment when constructing the ActionBar. It’s pretty straightforward; mostly just inflating its layout. We also set the content of the TextView (you’ll need to edit values/strings.xml
accordingly to provide this string resource). You could also make other changes to the tab, such as background colour, here.
FragmentTab2.java and FragmentTab3.java are nearly identical except that the text string will be R.string.Two
and R.string.Three
respectively. (You will notice that this could use a bit of refactoring to avoid code repetition. You could set up the Fragments to use the text strings as arguments in a Bundle, but that is beyond the scope of this tutorial.)
Creating the TabListener
The last bit of active code before we move onto the XML files is the MyTabListener class:
public class MyTabListener implements ActionBar.TabListener { Fragment fragment; public MyTabListener(Fragment fragment) { this.fragment = fragment; } public void onTabSelected(Tab tab, FragmentTransaction ft) { ft.replace(R.id.fragment_container, fragment); } public void onTabUnselected(Tab tab, FragmentTransaction ft) { ft.remove(fragment); } public void onTabReselected(Tab tab, FragmentTransaction ft) { // nothing done here } }
FragmentTransaction provides the API for various fragment operations. Each set of changes to a fragment in your activity (removing it, replacing it with another fragment, adding it, and so on) is called a transaction and is managed through FragmentTransaction. As well as allowing you to perform a set of changes all at once, you can also add transactions to the back stack, which allows users to navigate backwards through changes they have made. However, in this case we’re not directly managing any transactions ourselves, just adding something to a transaction which the main activity (and the ActionBar) will manage for us.
So for each callback the Listener gets, it adds the appropriate transaction to the FragmentTransaction passed in at the time. If the tab is selected, the current fragment replaces the old one in the fragment container, and if it’s unselected, it is removed. This could of course be made much more complicated if your code requires it.
Layouts
Having written all the code, we need to create our XML layouts. The main layout, activity_tab_test.xml
, is just a container for the tab fragments:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" />
This is the R.id.fragment_container
referred to in the MyTabListener code, that each fragment will be replaced into as its tab is selected. It’s just a single frame, covering the whole screen (the tab titles go in the ActionBar which has its own Android-generated layout).
Next we need the tab layout, tab.xml
:
<?xml version="1.0" encoding="utf-8"?> <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" > <TextView android:id="@+id/tabtextview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" /> </RelativeLayout>
Another simple layout: this one just has a single TextView, which we put our string resource into in the FragmentTab* classes. If you wanted your tabs to be more different from one another, you could create multiple layouts and use a different one in each tab class. This layout will be dropped into the FrameLayout of the main Activity XML.
All the pieces of your code are now together; run it and you should get a tabbed activity that looks a bit like the screen capture, above.
As ever, this is a simple example of a structure that can get very complicated if you want it to. Experiment further and see what simple and more complex layout options you can set up, and how you can manage different aspects of your app in a tab context. Tabs when used appropriately can provide a great UI, so they’re well worth getting to grips with.
This article concludes our series on Android App Development for Beginners. For the previous article in this series see:
How to Build a Contextual Menu in Android App Development
To start at the beginning visit: